/* ============================================================================
   ITOKAZE DS.
   components.css · the component layer. Depends on tokens.css.
   ----------------------------------------------------------------------------
   Every rule here is written through a token, never against a theme. If a
   selector mentions [data-theme] outside tokens.css, that is a bug.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

.ik {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--t-16);
  line-height: 1.5;
  position: relative;
  min-height: 100%;
  isolation: isolate;
  -webkit-font-smoothing: antialiased;
}

.ik::selection { background: var(--sig-quiet); color: var(--text); }

/* ---- Dry Obsidian / paper tooth ------------------------------------------
   Functional, not decorative: on dark it kills near-black banding, on light
   it gives the paper a tooth so flat fills do not read as plastic. */
.ik-grain::before {
  content: "";
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  opacity: var(--grain-opacity);
  mix-blend-mode: var(--grain-blend);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.35'/%3E%3C/svg%3E");
}

/* ============================================================================
   TYPE
   ========================================================================== */
.ik-display {
  font-family: var(--font-display);
  /* weight 500, not 700. The width axis carries the emphasis, so the weight
     axis does not have to — and Saira's expanded cuts hold their squared
     skeleton far better at Medium than at Black. */
  font-weight: 500;
  font-variation-settings: "wdth" var(--wdth-wide);
  letter-spacing: var(--track-display);
  line-height: 1.05;
  text-wrap: balance;
}
.ik-display--lg {
  font-size: clamp(var(--t-38), 6vw, var(--t-90));
  font-variation-settings: "wdth" var(--wdth-hero);
  letter-spacing: var(--track-display-lg); line-height: 1.02;
}
.ik-display--md { font-size: clamp(var(--t-28), 4vw, var(--t-50)); }
.ik-display--sm {
  font-size: clamp(var(--t-21), 2.6vw, var(--t-28)); line-height: 1.15;
  /* below ~24px the expanded cut crowds its counters — drop to normal width */
  font-variation-settings: "wdth" var(--wdth-normal);
}

.ik-wordmark {
  font-family: var(--font-display);
  font-weight: 600;
  font-variation-settings: "wdth" var(--wdth-hero);
  letter-spacing: var(--track-wordmark);
  line-height: 1;
  text-transform: uppercase;
}

.ik-kicker,
.ik-index {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: var(--track-label);
  line-height: 1.4;
  text-transform: uppercase;
}
.ik-kicker { color: var(--sig); }
.ik-index { color: var(--text-2); }
.ik-index > strong {
  color: var(--sig);
  font-family: var(--font-display);
  font-size: var(--t-28);
  font-variation-settings: "wdth" var(--wdth-tight);
  font-weight: 400;
  letter-spacing: -0.03em;
}

.ik-body { font-size: var(--t-16); line-height: 1.5; max-width: 66ch; }
.ik-body--muted { color: var(--text-2); }

/* Dense data sits at the CONDENSED end of the width ladder. This is not a
   preference — it is what keeps hierarchy-by-width working. Saira tops out at
   wdth 125, so the expanded end alone buys only a 17% gain over normal; the
   span only becomes usable if the narrow end is genuinely occupied. Put the
   spec tables, size ladders and numeric columns here and the hero reads as a
   hero without a single unit of added tracking. */
.ik-data { font-variation-settings: "wdth" var(--wdth-data); }
.ik-data--tight { font-variation-settings: "wdth" var(--wdth-tight); }

/* Mono is reserved for machine-truth: measurements, lot codes, prices, stock
   counts, sizes, timestamps, filament codes. Nothing a human would say aloud. */
.ik-mono {
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: var(--track-mono);
  text-transform: uppercase;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.ik-mono--13 { font-size: var(--t-13); }
.ik-mono--sig { color: var(--sig); }
.ik-mono--state { color: var(--state-text); }   /* the AA-safe variant, always */


/* ============================================================================
   THE FILAMENT RAIL
   A hairline on the baseline of every display line, running past the text to
   the grid edge — the thread the words are strung on. It breaks with a 13px
   gap exactly where another element attaches below, so the rail documents the
   structure of the page. Never doubled, never dashed, never decorative.
   ========================================================================== */
.ik-rail { position: relative; padding-bottom: var(--pitch); }
.ik-rail::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0;
  height: 1px; background: var(--text-3);
}
.ik-rail--lit::after {
  background: var(--sig);
  filter: var(--sig-glow);   /* resolves to `none` on paper */
}

/* ============================================================================
   THE FAULT — one 22.5° diagonal per composition, and it must touch the
   subject. It is never decorative on its own: it is the line along which
   something changes.

   Drawn as a background gradient rather than a rotated element, because a
   background clips to its own box for free. The rotated-element version
   needed `overflow: hidden` on the section, which then cropped anything
   deliberately positioned outside its box — the Metric Reticle's value sits
   at top:-16px, so the section was silently eating the number and breaking
   the system's own "no reticle without a number" rule. It also cropped the
   2px-offset focus ring of any control near the section edge.
   ========================================================================== */
.ik-fault { position: relative; }
.ik-fault::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(var(--fault-axis),
      transparent calc(62% - 0.5px),
      var(--line)  calc(62% - 0.5px),
      var(--line)  calc(62% + 0.5px),
      transparent  calc(62% + 0.5px));
}

/* Half-Pitch Shear — any modular field crossing the Fault offsets by exactly
   half its own module, so the two sides interlock rather than misalign. */
.ik-shear > :nth-child(even) { transform: translateY(var(--shear)); }

/* ============================================================================
   METRIC RETICLE
   Four corner ticks bracketing a region, with a real measured value outside
   the top-right. THE RULE: no reticle without a number, and the number must
   be true. Reticles never appear ON a photograph, only in layout beside one.
   ========================================================================== */
.ik-reticle { position: relative; }
.ik-reticle > .tick { position: absolute; width: 8px; height: 8px; border: 0 solid var(--text-3); }
.ik-reticle > .tl { top: 0; left: 0;  border-top-width: 1px; border-left-width: 1px; }
.ik-reticle > .tr { top: 0; right: 0; border-top-width: 1px; border-right-width: 1px; }
.ik-reticle > .bl { bottom: 0; left: 0;  border-bottom-width: 1px; border-left-width: 1px; }
.ik-reticle > .br { bottom: 0; right: 0; border-bottom-width: 1px; border-right-width: 1px; }
.ik-reticle > .val {
  position: absolute; top: -16px; right: 0;
  font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: var(--track-mono); text-transform: uppercase;
  color: var(--text-2); font-variant-numeric: tabular-nums;
}

/* ============================================================================
   HORIZON CHROME — theme-invariant. One room, reflected everywhere.
   ========================================================================== */
.ik-chrome { background: var(--chrome); position: relative; }
.ik-chrome::after {
  content: ""; position: absolute; left: 0; right: 0;
  top: var(--chrome-break); height: 1px; background: var(--chrome-specular);
}

/* ============================================================================
   MATERIAL + TECHNICAL SURFACES
   The references use chrome, holographic film and digital framing repeatedly.
   These primitives make that language reusable without baking a theme into a
   page. Light mode keeps the material reflective but removes all emission.
   ========================================================================== */
.ik-tech-grid {
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: 32px 32px;
}

.ik-tech-frame {
  position: relative;
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-panel);
  background:
    linear-gradient(var(--sig), var(--sig)) left 14px top 14px / 22px 1px no-repeat,
    linear-gradient(var(--sig), var(--sig)) left 14px top 14px / 1px 22px no-repeat,
    linear-gradient(var(--state), var(--state)) right 14px bottom 14px / 22px 1px no-repeat,
    linear-gradient(var(--state), var(--state)) right 14px bottom 14px / 1px 22px no-repeat,
    var(--glass);
  box-shadow: var(--panel-shadow);
}

.ik-glass {
  background: var(--glass);
  border: 1px solid var(--glass-line);
  border-radius: var(--radius-panel);
  box-shadow: var(--panel-shadow);
  backdrop-filter: blur(16px) saturate(120%);
  -webkit-backdrop-filter: blur(16px) saturate(120%);
}

.ik-holographic { background: var(--holographic); color: #0A0C0D; }
.ik-signal-spectrum { background: var(--signal-spectrum); }

/* ============================================================================
   BUTTONS
   Primary never fills with neon. An emerald filament sweeps the bottom edge.
   ========================================================================== */
.ik-btn {
  font-family: var(--font-body); font-weight: 600; font-size: var(--t-16);
  letter-spacing: var(--track-label); text-transform: uppercase;
  font-variation-settings: "wdth" var(--wdth-data);
  border-radius: var(--radius); border: 0;
  min-height: 48px; padding: 0 var(--s-3);
  display: inline-flex; align-items: center; justify-content: center;
  cursor: pointer; position: relative; overflow: hidden;
  transition: background var(--dur-micro) var(--ease-micro),
              color var(--dur-micro) var(--ease-micro);
}
.ik-btn:disabled { cursor: wait; opacity: .58; }
.ik-btn--primary { background: var(--text); color: var(--bg); }
.ik-btn--primary::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
  background: var(--sig); filter: var(--sig-glow);
  transform: scaleX(0); transform-origin: left;
  transition: transform 220ms var(--ease-micro);
}
.ik-btn--primary:hover::after,
.ik-btn--primary:focus-visible::after { transform: scaleX(1); }

.ik-btn--secondary { background: transparent; color: var(--text); box-shadow: inset 0 0 0 1px var(--line-control); }
.ik-btn--secondary:hover { box-shadow: inset 0 0 0 1px var(--text); }

/* Destructive is outlined, never filled — magenta is a state, not a surface. */
.ik-btn--destructive { background: transparent; color: var(--state-text); box-shadow: inset 0 0 0 1px var(--state); }

/* ============================================================================
   INPUTS — no box. A mono label, a value, and the Filament Rail as underline.
   ========================================================================== */
/* min-width:0 lets a field shrink inside grid/flex tracks; without it the
   input's intrinsic width becomes the field's floor and narrow layouts clip. */
.ik-field { display: flex; flex-direction: column; gap: var(--s-1); min-width: 0; }
.ik-field > label {
  font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: var(--track-mono); text-transform: uppercase; color: var(--text-2);
}
.ik-field > input, .ik-field > select {
  width: 100%; min-width: 0; box-sizing: border-box;
  font-family: var(--font-body); font-size: var(--t-16);
  color: var(--text); background: transparent;
  border: 0; border-bottom: 1px solid var(--line-control);
  border-radius: 0; padding: 10px 0; min-height: 44px;
  transition: border-color var(--dur-micro) var(--ease-micro);
}
.ik-field--box { gap: 6px; }
.ik-field--box > input,
.ik-field--box > select {
  min-height: 50px;
  padding: 11px 13px;
  background: var(--glass-strong);
  border: 1px solid var(--line-control);
  border-radius: var(--radius);
}
.ik-field--box > input:focus-visible,
.ik-field--box > select:focus-visible { border-color: var(--sig); }
.ik-field--box[data-invalid="true"] > input,
.ik-field--box[data-invalid="true"] > select { border-color: var(--state); }
/* NB: no `outline: none` here. §8 says the focus ring is never removed, and
   the global :focus-visible rule must be allowed to place it. The underline
   is an ADDITION to the ring, not a replacement for it. */
.ik-field > input:focus-visible { border-bottom-color: var(--sig); }
.ik-field[data-invalid="true"] > input { border-bottom-color: var(--state); }
/* The Vibration Rule: emerald and magenta never share an edge. On an invalid
   field the ring is 2px offset from the magenta underline, which supplies the
   required ground gap — but the emerald underline would sit flush against it,
   so error keeps its own colour and focus is carried by the offset ring alone. */
.ik-field[data-invalid="true"] > input:focus-visible { border-bottom-color: var(--state); }
.ik-field > .err {
  font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: var(--track-mono); text-transform: uppercase; color: var(--state-text);
}

/* ============================================================================
   STATE CHIPS — the only fully rounded object. If it is round, it is a live fact.
   ========================================================================== */
.ik-chip {
  display: inline-flex; align-items: center; gap: 6px;
  /* a chip states one live fact, so it is only ever as wide as that fact —
     it must not stretch when it lands in a flex-column or a grid cell */
  align-self: flex-start; width: fit-content;
  border-radius: var(--radius-state);
  padding: 4px 10px;
  font-family: var(--font-mono); font-size: var(--t-11);
  letter-spacing: var(--track-mono); text-transform: uppercase;
  font-variant-numeric: tabular-nums;
  background: transparent;
}
.ik-chip--live  { color: var(--sig);        box-shadow: inset 0 0 0 1px var(--sig); }
.ik-chip--state { color: var(--state-text); box-shadow: inset 0 0 0 1px var(--state); }
.ik-chip--quiet { color: var(--text-2);     box-shadow: inset 0 0 0 1px var(--line); }

/* ============================================================================
   THE 4% AREA LAW
   Any signal region larger than 4% of the viewport must use its quiet state.
   Dark: unlit emerald. Light: emerald tint. Same threshold, different physics,
   because saturation is loud on paper too.
   Apply .ik-area--quiet to any panel, banner or hero block carrying signal.
   ========================================================================== */
.ik-area--quiet { background: var(--sig-quiet); color: var(--text); }
.ik-area--state-quiet { background: var(--state-quiet); color: var(--text); }

/* Compact theme control shared by demos and product surfaces. */
.ik-theme-toggle {
  min-height: 42px;
  padding: 0 13px;
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--text);
  background: var(--glass);
  border: 1px solid var(--line-control);
  border-radius: var(--radius);
  font-family: var(--font-mono);
  font-size: var(--t-11);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  cursor: pointer;
}
.ik-theme-toggle::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--sig);
  filter: var(--sig-glow);
}
.ik-theme-toggle:hover { border-color: var(--text); }

/* ============================================================================
   FOCUS — the single most emerald thing in the interface. Never removed.

   The ring is delivered as `outline` ONLY. It must never touch `box-shadow`,
   because box-shadow is the property every ringed component uses for its 1px
   border — a focus rule that sets it erases the border instead of adding to
   it, and on the light theme, where the glow token is `none`, the border
   simply disappears the moment a keyboard user reaches the control.
   The emission is carried by `filter` on the elements that emit.
   ========================================================================== */
:where(.ik) :focus-visible {
  outline: 2px solid var(--sig);
  outline-offset: 2px;
}

/* ============================================================================
   MOTION
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .ik *, .ik *::before, .ik *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* Nothing is pinned on here: killing the transition above already removes
     the animation while leaving hover and focus as real state changes. */
}
