/* ============================================================
   NARUTO Card Game Sim — base: reset, theme tokens, typography,
   layout primitives. Component styles live in components.css.
   ============================================================ */

/* ---- Fonts (self-hosted; fall back to system stacks until the
   woff2 files are dropped into assets/fonts/) ---- */
@font-face {
  font-family: 'Anton';
  src: url('../fonts/anton-v25-latin-regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
/* Body face is Archivo (SIL OFL), not Inter.
   Inter is the single most recognisable marker of a generated-looking site —
   it is the default nearly every tool reaches for. Archivo is a grotesque
   drawn for high-contrast display and small text at the same time: slightly
   squarer terminals and a taller x-height, which sits with Anton's condensed
   weight instead of fighting it. */
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-latin-400.woff2') format('woff2');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-latin-600.woff2') format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-latin-700.woff2') format('woff2');
  font-weight: 700; font-style: normal; font-display: swap;
}

/* ---- Theme tokens ----
   The village, not a generic dark UI. Two material families do the work:
   FOREST (the ground the village stands in — bark, canopy, leaf) and
   PAPER (mission scrolls and the washi the rules are printed on). Naruto's
   jacket orange stays the ACTION colour on top of both, which is also the
   division worth keeping: green is the village and the furniture, orange is
   the thing you click. */
:root {
  /* Konoha after dark: a green-black forest floor, not a neutral charcoal. */
  --bg: #101710;
  --bg-elev: #18211a;
  --bg-deep: #0a0f0a;
  --panel: rgba(125, 196, 92, 0.05);
  --panel-hover: rgba(125, 196, 92, 0.10);
  --line: rgba(139, 200, 110, 0.16);
  --line-strong: rgba(139, 200, 110, 0.36);
  --text: #f0ece0;
  --muted: #9fae96;

  --orange: #e8630a;      /* primary: Naruto jacket orange */
  --orange-hot: #ff8a3d;  /* hover / glow */
  --red: #e23b0d;         /* the NARUTO logo red: danger, live badges */
  --gold: #f2b23e;        /* rarity / highlight */
  --green: #4ade80;       /* success / ready */
  --blue: #60a5fa;        /* info */

  /* ---- Village materials ---- */
  --leaf: #5b9c3e;        /* Konoha green: the flak jacket, the canopy */
  --leaf-bright: #86ca63;  /* leaf on a dark ground, readable as text */
  --bark: #2b2118;        /* timber: frames, posts, notice boards */
  --bark-light: #4a382a;
  --scroll: #e7dcc1;      /* washi — the mission scroll the rules sit on */
  --scroll-edge: #cbbc9a;
  --scroll-ink: #241d14;  /* sumi ink on that scroll */
  --scroll-ink-soft: #5b4f3c;
  --seal: #b3341f;        /* hanko red: the stamp, the step numbers */

  /* Asanoha (hemp leaf) — the textile pattern the page is woven on. Tuned per
     theme because a black-line tile has to sit at a different strength on a
     dark ground than on paper. */
  --texture: url('../img/asanoha.svg');
  --texture-color: #8fd06a;   /* the weave lit against the forest floor */
  --texture-opacity: 0.085;
  /* The Konohagakure leaf, used as a MASK wherever it needs to take a colour
     from the page (see .section-title::before). tools/gen_leaf.py draws it. */
  --leaf-mark: url('../img/konoha_leaf.svg');

  /* The room's accent. room.css leans on this ~15 times — selection outlines,
     the "your turn" bar, the action-menu border and its hover row — and it was
     never actually DEFINED. An undefined custom property is invalid at
     computed-value time, so every one of those declarations was silently thrown
     away: no outline on a selected attacker, no border on the turn bar, and, the
     visible one, `.ca-btn:hover { background: var(--accent); color: #fff }`
     applying only the WHITE TEXT. On the light theme's near-white popover that
     is white on white — the action menu row went blank the moment you pointed at
     it. Silent is the problem here: a typo'd colour shows up, a typo'd token
     just quietly does nothing. */
  --accent: var(--orange);
  /* Accent as a FILL behind white text. The plain accent is too light for that:
     #fff on #e8630a is 3.4:1, under the 4.5:1 normal-text minimum, and the
     action-menu rows are .82rem. #c2510a takes it to 4.7:1 and still reads as
     the same orange. Works on both themes, since the text on it is always white. */
  --accent-fill: #c2510a;

  --grad-primary: linear-gradient(135deg, #f97b1c, #e8630a 55%, #e23b0d);
  --glow-orange: 0 0 24px rgba(232, 99, 10, 0.35);
  /* Section rules and village furniture. Kept SEPARATE from --grad-primary on
     purpose: that one is the button fill, and repointing it to green would take
     every call to action with it. */
  --grad-leaf: linear-gradient(90deg, #86ca63, #5b9c3e 70%, #3d7028);

  --radius: 14px;
  --radius-sm: 9px;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  --shadow-lift: 0 18px 44px rgba(0, 0, 0, 0.55);

  --font-display: 'Anton', 'Arial Narrow', Impact, sans-serif;
  --font-body: 'Archivo', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', sans-serif;

  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* Floating surfaces — action menus, the chain column, any popover.
     These exist because those panels used to hard-code a near-black background
     while taking their text from var(--text). In light mode that is dark text on
     a near-black panel: every dropdown and command menu in the room became
     unreadable. A surface that paints its own background needs a token that
     moves with the theme, exactly like --bg-elev does. */
  --popover: rgba(12, 12, 16, 0.97);
  --popover-shadow: 0 14px 40px rgba(0, 0, 0, 0.65);
}

/* Daylight over the village: washi paper rather than white, so the light theme
   is the same village at noon instead of a different product. */
html[data-theme='light'] {
  --bg: #f4f1e3;
  --bg-elev: #fffdf4;
  --bg-deep: #e6e1cd;
  --panel: rgba(61, 112, 40, 0.05);
  --panel-hover: rgba(61, 112, 40, 0.10);
  --line: rgba(58, 92, 40, 0.20);
  --line-strong: rgba(58, 92, 40, 0.42);
  --text: #1d2418;
  --muted: #5d6b54;
  --shadow: 0 10px 28px rgba(40, 55, 30, 0.12);
  --shadow-lift: 0 18px 40px rgba(40, 55, 30, 0.18);
  --glow-orange: 0 0 20px rgba(232, 99, 10, 0.22);
  --popover: #fffdf4;
  --popover-shadow: 0 14px 40px rgba(40, 55, 30, 0.22);

  /* On paper the mid greens stop carrying enough contrast, so the village
     tokens darken rather than the layout swapping to a different colour. */
  --leaf: #3d7028;
  --leaf-bright: #33601f;
  --scroll: #fbf6e6;      /* the scroll lifts OFF the page here, not out of the dark */
  --scroll-edge: #d9cba6;
  --texture-color: #2f4a22;   /* on paper the weave is printed, so it darkens */
  --texture-opacity: 0.13;
}

/* ---- Reset ---- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.55;
  /* Two soft gradient blooms used to float here. They are the decorative
     default — the thing that reads as "generated" precisely because it is
     applied without reference to what is on the page. What replaced them is
     not a bloom but a MATERIAL: asanoha, the hemp-leaf textile pattern, woven
     flat across the ground at low opacity. It is a real pattern with a reason
     to be on a Konoha page, and it reads as cloth rather than as lighting. */
  background-image: none;
}
/* The weave is its own layer so its opacity is independent of the content, and
   fixed so the page moves over the cloth instead of dragging it along.

   MASKED rather than drawn: the tile's lines are black, and painting black
   lines onto a near-black forest floor is invisible at any opacity that is
   still tasteful — darkening something already dark has nowhere to go. As a
   mask the tile only supplies the SHAPE and --texture-color supplies the ink,
   so the dark theme lightens the weave and the light theme darkens it. */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-color: var(--texture-color);
  -webkit-mask-image: var(--texture);
          mask-image: var(--texture);
  -webkit-mask-repeat: repeat;
          mask-repeat: repeat;
  opacity: var(--texture-opacity);
}
img { max-width: 100%; display: block; }
a { color: var(--orange-hot); text-decoration: none; }
a:hover { text-decoration: underline; }
button, input, select, textarea { font: inherit; color: inherit; }
h1, h2, h3, h4 { line-height: 1.15; margin: 0 0 0.5em; }

/* ---- Display typography ---- */
.display {
  font-family: var(--font-display);
  font-weight: 400;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
h1.display { font-size: clamp(38px, 6vw, 72px); }
h2.display { font-size: clamp(26px, 4vw, 40px); }

/* Section heading: the village leaf, then the title, over a green rule.
   The rule is leaf green rather than orange so a heading never competes with a
   button for "this is the thing to press". */
.section-title {
  display: flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-display);
  font-size: clamp(24px, 3.4vw, 34px);
  text-transform: uppercase;
  letter-spacing: 0.03em;
  margin-bottom: 6px;
}
.section-title::before {
  content: '';
  flex: none;
  width: 0.86em;
  height: 0.86em;
  background: var(--grad-leaf);
  /* Masked rather than an <img>: the mark ships with fill="currentColor", which
     an <img> resolves against the SVG's OWN document (i.e. black), so a mask is
     the only way the leaf takes a colour from the page. */
  -webkit-mask: var(--leaf-mark) no-repeat center / contain;
          mask: var(--leaf-mark) no-repeat center / contain;
}
.section-title::after {
  content: '';
  flex: 1 1 auto;
  height: 2px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--line-strong), transparent 88%);
}
.section-eyebrow {
  color: var(--orange-hot);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  margin: 0 0 6px;
}
.section-sub { color: var(--muted); margin: 0 0 22px; max-width: 640px; }

/* ---- Layout primitives ---- */
.wrap {
  width: min(1280px, calc(100% - 32px));
  margin-inline: auto;
}
.wrap-narrow { width: min(880px, calc(100% - 32px)); margin-inline: auto; }
.stack-lg > * + * { margin-top: 56px; }
.grid-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.row { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.spacer { flex: 1 1 auto; }
.muted { color: var(--muted); }
.hidden { display: none !important; }

@media (max-width: 820px) {
  .grid-2, .grid-3 { grid-template-columns: 1fr; }
}

/* ---- Landscape is not supported on a phone ----
   The board is a fixed-viewport layout: two players' rows, a midline and a hand,
   stacked. That needs HEIGHT, and a phone on its side has about 390px of it —
   less than the portrait width it was designed against. Rather than ship a board
   whose rows are each a few pixels tall, the page asks to be turned upright.

   `max-height: 500px` with landscape is what picks out a phone specifically: a
   tablet or a laptop in landscape is taller than that, so neither ever sees
   this. Orientation alone would catch every desktop monitor ever made.

   A real orientation LOCK is not available here — screen.orientation.lock()
   only applies in fullscreen, which a page cannot enter without a gesture — so
   the honest version is a gate that covers the page until it is turned back. */
/* The default MUST come before the media query. A media query adds nothing to
   specificity, so `.rotate-gate { display: none }` written afterwards would beat
   the `display: flex` inside it at equal specificity and the gate would never
   appear — which is exactly what happened the first time. Same trap the phone
   board rules in room.css carry a note about. */
.rotate-gate { display: none; }
@media (orientation: landscape) and (max-height: 500px) {
  .rotate-gate {
    position: fixed;
    inset: 0;
    z-index: 9999;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    text-align: center;
    background: var(--bg);
    /* The board keeps polling and playing underneath; this only stops it being
       looked at sideways. */
  }
  /* Nothing behind it should be reachable or scrollable while it is up. */
  body { overflow: hidden !important; }
}
.rotate-gate-inner { max-width: 34ch; }
.rotate-gate-inner b {
  display: block;
  font-family: var(--font-display);
  font-size: 1.3rem;
  text-transform: uppercase;
  letter-spacing: .02em;
  margin-bottom: 6px;
}
.rotate-gate-inner p { color: var(--muted); font-size: .86rem; margin: 0; }
/* A phone outline that turns upright — the instruction, drawn. */
.rotate-gate-icon {
  display: block;
  width: 34px;
  height: 54px;
  margin: 0 auto 14px;
  border: 2.5px solid var(--leaf-bright);
  border-radius: 7px;
  animation: rotate-hint 2.2s ease-in-out infinite;
}
@keyframes rotate-hint {
  0%, 30%   { transform: rotate(90deg); }
  55%, 100% { transform: rotate(0deg); }
}
@media (prefers-reduced-motion: reduce) {
  .rotate-gate-icon { animation: none; }
}

/* ---- No sideways scrolling on a phone ----
   A page that slides left and right is broken on a touch screen in a way it is
   not on a desktop: a horizontal swipe is how you scroll a list, drag a card, or
   go back, so an overflowing page steals gestures the app itself needs. This is
   the backstop, not the fix — anything wide enough to trigger it (a table, a
   card row) should scroll INSIDE its own container. Set on both html and body
   because `overflow-x` on body alone is propagated to the viewport only when
   html is `visible`, which it is not once a page sets its own overflow. */
@media (max-width: 820px) {
  html, body { max-width: 100%; overflow-x: hidden; }
}

/* ---- Accessibility ---- */
:focus-visible {
  outline: 2px solid var(--orange-hot);
  outline-offset: 2px;
  border-radius: 4px;
}
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
