/* ===========================================================================
   THE SITE THEME: BONE, BLOOD, AND A NEAR-BLACK GROUND
   ===========================================================================

   > "White represents bone and red means blood."
   > "panels can be outlined in red not black and buttons should all be red."
   > "Turn the background to a very dark black."

   THREE THINGS AND EACH HAS ONE JOB, which is the wordmark's own rule applied
   to a whole site rather than to a header:

     GROUND  near-black, and textured. A repeating pixel tile, not a flat fill.
             See `tools/makedirt.mjs`: it is the board's own earth at #605038
             taken down to about five percent lightness rather than a black
             picked off a swatch, which is why it is not #000 — pure black has
             no hue to be consistent with, and a page with no hue in it reads
             as a switched-off screen rather than as night.
     BONE    the voice. Headings, names, anything that is the subject.
     BLOOD   every edge and every button. Not an accent used sparingly: on this
             site red is the structural colour, and that is the difference
             between a site that has the logo on it and a site that looks like
             the logo.

   RED EDGES RATHER THAN BLACK ONES. A black outline on a dark panel over a
   darker ground separates the two and says nothing else. Red separates them
   just as well and puts the theme on the one element that appears on every
   panel on every page — which is more red than any amount of accent colour
   could buy.

   A DEEPER RED FOR A LINE THAN FOR A FILL. `--blood` at #d92433 is sized to be
   read as a surface; a hairline in it against near-black glows. `--blood-line`
   is the same colour with the light taken out: it holds an edge, it still
   reads unmistakably red, and it does not fight the text inside the panel it
   is drawing.

   GOLD SURVIVES, AND ONLY AS MONEY. Prices, purses, the pot. Every button that
   used to be gold on these three pages is now red, which finally settles the
   argument the palette was having with itself: gold is what an amount is
   written in and red is what you press.

   SCOPED BY ROOT ATTRIBUTE. `styles.css` is the game's sheet and every page
   loads it for the type scale and the shared furniture; redefining the TOKENS
   under `[data-site]` re-themes everything that reads them without touching a
   rule in that file. The game carries none of these attributes and is
   untouched — and should be: a board is a place you look into for an hour, a
   page is a thing you look at for ninety seconds.
   =========================================================================== */

html[data-site], html[data-store], html[data-admin] {
  --bg:         #0c0a08;
  --bg-panel:   #14110d;
  --bg-raise:   #1c1813;
  --line:       #2b241c;
  --ink:        #f4efe2;
  --ink-dim:    #c3b6a0;
  --ink-faint:  #92836c;

  --gold:       #e8b44e;
  --good:       #7fc08a;
  --warn:       #dfa863;
  --bad:        #e0685a;
  --accent:     #6fb3bf;

  --bone:       #f4efe2;
  --blood:      #d92433;
  --blood-line: #9c1622;
  --blood-deep: #6d0f18;
  --outline:    #0d0a08;
}

/* THE GROUND. `background-attachment: fixed` deliberately not used: it forces a
   full-page repaint on every scroll on mobile, and a 32-pixel tile is free to
   scroll. 64px draws each of its pixels at two, so it stays visibly pixel art
   rather than becoming a vague mottle. */
html[data-site] body, html[data-store] body, html[data-admin] body {
  background-color: var(--bg);
  background-image: url("img/dirt.svg");
  background-size: 64px 64px;
  background-repeat: repeat;
  color: var(--ink);
}

/* --- every panel, one edge ------------------------------------------------ */
html[data-site] .side, html[data-site] .figs, html[data-site] .beats,
html[data-store] .gate, html[data-store] .preview, html[data-store] .support,
html[data-admin] .dc-card, html[data-store] .dc-card, html[data-site] .dc-card {
  background: var(--bg-panel);
  border: 2px solid var(--blood-line);
  box-shadow: 0 4px 0 rgba(0, 0, 0, .55);
}
/* The two grids draw their dividers with the gap, so the gap has to be the edge
   colour or the hairlines inside them stay dark while the frame is red. */
html[data-site] .figs, html[data-site] .beats { background: var(--blood-line); gap: 2px; }
html[data-site] .figs div, html[data-site] .beat { background: var(--bg-panel); }

html[data-store] .card, html[data-store] .band,
html[data-store] .store-top, html[data-admin] .dc-bar {
  border-color: var(--blood-line);
}

/* --- every button --------------------------------------------------------- */
/* Two selector sets because the site's own buttons and the store's plain
   elements never shared a class. */
/* NOT `.card`, AND THAT EXCLUSION IS THE WHOLE DIFFERENCE BETWEEN A THEME AND
   A WALL. The store's character tiles are `<button>` elements -- they are
   pressable, so the markup is right -- and a blanket "every button is red"
   turned forty-three of them into one red field with the sprites lost inside
   it. A tile is a thing you CHOOSE, not a thing you DO; it gets the panel
   treatment below and wears red only when it is the one you are wearing. */
html[data-store] .dc-btn, html[data-admin] .dc-btn,
html[data-store] button:not(.card):not(.dc-pill),
html[data-admin] .dc-gold, html[data-store] .dc-gold {
  background: var(--blood);
  color: var(--bone);
  border: 2px solid var(--blood-line);
  border-radius: 0;
  box-shadow: 0 4px 0 var(--blood-deep);
}
html[data-store] .dc-btn:hover, html[data-admin] .dc-btn:hover,
html[data-store] button:hover:not(:disabled):not(.card):not(.dc-pill),
html[data-admin] .dc-gold:hover, html[data-store] .dc-gold:hover {
  background: #e83544;
}
html[data-store] .dc-btn:active, html[data-admin] .dc-btn:active,
html[data-store] button:active:not(:disabled):not(.card):not(.dc-pill),
html[data-admin] .dc-gold:active, html[data-store] .dc-gold:active {
  transform: translateY(4px);
  box-shadow: 0 0 0 var(--blood-deep);
}

/* THE QUIET ONE STAYS QUIET, and this exception is what keeps the rule usable.
   A screen where every control is the loudest colour has no primary at all — so
   the secondary action keeps a dark fill and wears the red as its edge and its
   text. It is still unmistakably part of the set. */
html[data-store] .dc-ghost, html[data-admin] .dc-ghost {
  background: var(--bg-raise);
  color: #f0808c;
  border-color: var(--blood-line);
  box-shadow: 0 4px 0 rgba(0, 0, 0, .5);
}
html[data-store] .dc-ghost:hover, html[data-admin] .dc-ghost:hover { background: #241d17; }

/* A disabled control must not read as the most urgent thing on the page. */
html[data-store] button:disabled:not(.card), html[data-admin] .dc-btn:disabled {
  background: var(--bg-raise);
  color: var(--ink-faint);
  border-color: var(--line);
  box-shadow: 0 4px 0 rgba(0, 0, 0, .4);
}
html[data-store] button:disabled:active, html[data-admin] .dc-btn:disabled:active {
  transform: none;
}

html[data-store] .dc-nav a.dc-cta, html[data-admin] .dc-nav a.dc-cta {
  background: var(--blood);
  color: var(--bone);
  border: 2px solid var(--blood-line);
  border-radius: 0;
  box-shadow: 0 3px 0 var(--blood-deep);
}
html[data-store] .dc-nav a.dc-cta:hover, html[data-admin] .dc-nav a.dc-cta:hover {
  background: #e83544;
}

/* THE PREMIUM SWITCH IS A STATE, NOT AN ACTION, so it stays gold when it is on.
   Red there would say "press me" about the thing that has already been
   pressed, which is the one job red must not take on this page. */
html[data-admin] .dc-pill.is-on {
  background: var(--gold);
  border-color: var(--blood-line);
  color: #241a06;
}


/* ---------------------------------------------------------------------------
   THE WEBSITE'S OWN SHEET, ON TOP OF THE GAME'S TOKENS
   ---------------------------------------------------------------------------

   > "Center up the panels and make it more gamey/cartoony."

   `styles.css` holds the palette and the type scale, and every colour here comes
   out of it -- the rule `store.html` set, and the reason has not changed: a gold
   that reads one way on the site and another on the board is two products. What
   this file adds is the SHAPE.

   EVERY CLASS HERE IS PREFIXED `dc-`, AND THAT IS NOT TIDINESS.

   The first cut of this used `.panel`, `.topbar`, `.btn` and `.lede`. All four
   already exist in `styles.css`, and `.panel` there is `position: fixed`,
   translated off-screen and `visibility: hidden` until it gets `.is-open` --
   it is the game's slide-out side panel. So the admin page rendered five rows
   into the DOM and showed an empty screen. Nothing was wrong with the markup or
   the data; the game's furniture had eaten the layout.

   `store.html` had already written the warning and I did not heed it: "every
   rule below is scoped under `.store` and nothing on this page is styled by
   accident". A prefix is the cheapest possible version of that, and unlike
   scoping it cannot be defeated by a specificity tie.

   FOUR THINGS MAKE IT READ AS A GAME AND NONE IS A COLOUR:

     BIG SOFT CORNERS -- 18px against the game's 13. A tight radius reads as a
     form; rounded further it reads as a card off a table, which is what these
     are.

     BORDERS YOU CAN SEE -- two pixels, not one. The game's own furniture is
     hairline because it sits under a board and must not compete with it. A
     website has nothing to defer to, and a visible edge is what makes a panel
     an object rather than a region.

     A HARD SHADOW, not a blur. A soft drop-shadow is the house style of every
     SaaS page ever made; an offset block of near-black is a sticker on a table.

     BUTTONS THAT MOVE -- three pixels down on press with the shadow closing up
     under them. The cheapest imitation of a physical control, and the thing
     people read as "game" before they read anything.

   AND IT IS ALL CENTRED, which was asked for and is also right: these pages are
   one column of cards with nothing to put in a margin, so a left-aligned
   container just leaves a lake of empty on the right of a wide window.

   THE GAME'S VIEWPORT LOCK IS UNDONE HERE, ONCE, for every page that includes
   this. `styles.css` sets `html, body { height: 100%; overflow: hidden }` so the
   board never scrolls under the rail -- correct there, and on a page of prose it
   makes everything below the fold unreachable. It had been fixed twice by hand
   before this file existed, which is one time more than a rule should need.
--------------------------------------------------------------------------- */

html, body { height: auto; overflow: visible; }
html, body { background: var(--bg); color: var(--ink); margin: 0; }
body {
  font: var(--t-md)/var(--lh) ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  /* A quiet warm wash so a full-width dark page is not a flat rectangle.
     Fixed, so it does not travel with the scroll. */
  background-image: radial-gradient(1100px 620px at 50% -180px, #241c15 0%, var(--bg) 70%);
  background-attachment: fixed;
}
img { display: block; max-width: 100%; }

.dc-wrap { max-width: 1060px; margin: 0 auto; padding: 0 20px 90px; }

/* --- the bar ------------------------------------------------------------- */
.dc-bar { display: flex; align-items: center; gap: 16px; padding: 20px 0 26px;
          flex-wrap: wrap; justify-content: center; }
.dc-mark { font: 800 20px/1 ui-monospace, monospace; letter-spacing: .14em;
           text-transform: uppercase; color: var(--gold); text-decoration: none;
           text-shadow: 0 2px 0 #6b4e15; }
.dc-mark:hover { color: #f5cf76; }
.dc-nav { display: flex; gap: 16px; align-items: center; flex-wrap: wrap;
          justify-content: center; }
.dc-nav a { color: var(--ink-dim); text-decoration: none; font-size: var(--t-sm); }
.dc-nav a:hover { color: var(--ink); }
.dc-nav a.dc-cta { color: #2a1d06; background: var(--gold); padding: 9px 16px;
                   border-radius: 11px; font-weight: 700; box-shadow: 0 3px 0 #8a6410; }
.dc-nav a.dc-cta:hover { background: #f5cf76; }

/* --- cards --------------------------------------------------------------- */
.dc-card {
  background: var(--bg-panel);
  border: 2px solid var(--line);
  border-radius: 18px;
  padding: 26px;
  box-shadow: 0 4px 0 #100c09;
  margin: 0 auto 20px;
}
.dc-title { margin: 0 0 6px; font: 800 var(--t-xl)/1.15 ui-monospace, monospace;
            letter-spacing: -.01em; }
.dc-blurb { color: var(--ink-dim); margin: 0 0 18px; }
.dc-lab { display: block; font: 700 11px/1 ui-monospace, monospace; letter-spacing: .1em;
          text-transform: uppercase; color: var(--ink-faint); margin: 0 0 7px; }

.dc-card input, .dc-card select {
  background: var(--bg); color: var(--ink);
  border: 2px solid var(--line); border-radius: 10px;
  padding: 10px 12px; font: 14px ui-monospace, monospace;
}
.dc-card input:focus-visible, .dc-card select:focus-visible {
  outline: 3px solid var(--accent); outline-offset: 1px; border-color: var(--accent);
}

/* --- buttons that move --------------------------------------------------- */
.dc-btn {
  display: inline-block; text-decoration: none; text-align: center;
  border: 2px solid transparent; border-radius: 12px;
  padding: 11px 20px; font: 700 var(--t-md)/1.2 ui-sans-serif, system-ui, sans-serif;
  cursor: pointer; box-shadow: 0 4px 0 #100c09;
  transition: transform 60ms ease, box-shadow 60ms ease;
}
.dc-btn:active { transform: translateY(3px); box-shadow: 0 1px 0 #100c09; }
.dc-btn:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.dc-gold { background: var(--gold); color: #2a1d06; box-shadow: 0 4px 0 #8a6410; }
.dc-gold:active { box-shadow: 0 1px 0 #8a6410; }
.dc-gold:hover { background: #f5cf76; }
.dc-ghost { background: var(--bg-raise); color: var(--ink); border-color: var(--line); }
.dc-ghost:hover { border-color: var(--ink-faint); }

.dc-err { color: var(--bad); }
.dc-ok  { color: var(--good); }

.dc-foot {
  margin-top: 40px; padding-top: 18px; border-top: 2px solid var(--line);
  color: var(--ink-faint); font-size: var(--t-xs);
  display: flex; gap: 16px; flex-wrap: wrap; justify-content: center;
}
.dc-foot a { color: var(--ink-faint); }

@media (max-width: 640px) {
  .dc-card { padding: 20px; border-radius: 16px; }
  .dc-btn { width: 100%; box-sizing: border-box; }
}


/* --- the character tiles -------------------------------------------------- */
/* A dark slab on the ground like every other panel, with the red saved for the
   one that is actually on. A locked tile keeps the neutral edge: it is not an
   error and it is not urgent, it is simply not yours yet. */
html[data-store] .card {
  background: var(--bg-panel);
  border: 2px solid var(--line);
  border-radius: 0;
  box-shadow: 0 3px 0 rgba(0, 0, 0, .5);
}
html[data-store] .card:hover:not(.locked) { border-color: var(--blood-line); }
html[data-store] .card[aria-pressed="true"] {
  border-color: var(--blood);
  background: #21120f;
  box-shadow: 0 3px 0 var(--blood-deep);
}
html[data-store] .card[aria-pressed="true"] .cp { color: var(--blood); }
/* A LOCKED CARD DIMS ITS CHROME, NEVER ITS GOODS.

   `opacity: .5` on the whole card was dimming the swatch with everything else,
   which on a shelf is the one element that must not be touched: the six bright
   dyes exist to be bright, and a shopper was being shown a washed-out version
   of the thing they were being asked to pay for. A store that dims its own
   product is misrepresenting it.

   So the name, the price and the frame recede, and the colour is shown at full
   strength. Not-yet-yours is said by the muted label and the flat edge, which
   is enough -- the price underneath is already saying it too. */
html[data-store] .card.locked { opacity: 1; box-shadow: none; }
html[data-store] .card.locked .cn { color: var(--ink-faint); }
html[data-store] .card.locked .cp { color: var(--ink-faint); }
html[data-store] .card.locked { border-color: var(--line); }
/* The character sprites keep a slight knock-back, because a body is drawn art
   with its own colours and a locked one at full strength is indistinguishable
   from one you own. A flat swatch has no such ambiguity -- it is one colour and
   the label beneath it carries the state. */
html[data-store] .card.locked canvas { opacity: .55; }
