/* il-shapes.css — what each shape looks like standing still.
   ===========================================================================
   The seven shapes already owned an ENTRANCE (style.css, il-design-bridge.css)
   and a HOVER. What they did not own was a resting face. Photographed at
   rest, Frame, Blade, Cardinal and Cardinal 2.0 were the same dark rectangle
   with a different corner radius -- which is exactly what "the four shapes are
   too alike" meant, asked in four handoffs running. A shape you can only tell
   apart while it is animating is a shape you cannot tell apart.

   Each shape is a window system borrowed from somewhere, and this file gives
   each one the single mark that system is recognised by. The references are
   internal design language (theme.js keeps them out of shipped copy):

     soft        ordinary good product design            -> a lit top edge
     fluctlight  the lightcube -- particles, the world    -> a constellation
                 ("more inspired by particles and the world in general")
     frame       a tactical HUD                           -> brackets + ruler
     blade       the drawn sword                          -> one cut corner,
                                                             a polished edge
     cardinal    the original console, Aincrad-era        -> a riveted plate
     cardinal2   the console rebuilt ("based on the system design")
                                                          -> a title plate
     system      the Player's window                      -> a hologram frame
                                                             and the "!" mark

   The same identity reaches the landing page's own panels, so the shape you
   pick in the playground visibly changes the page you picked it on.

   CONSTRAINTS, each learned the hard way:
   - No ::before/::after on .card. il-aura.css spends both on every
     [data-il-panel] (the edge-light and the spotlight) and style.css spends
     .card.hero::before on the foil sweep. Everything here is background
     layers, box-shadow and clip-path, which compose with both.
   - Every colour is a token. The shapes repaint under all twelve moods.
   - No backdrop-filter: style.css records it as the most expensive thing on
     the page and every card is opaque anyway.
   - Loads LAST and is registered with scripts/check_css_specificity.py.
   =========================================================================== */

/* The panels a shape dresses: the terminal's cards and the landing page's own
   plates. The roster and the ladder rows are left alone -- their left edge is
   a class colour and a rank band, which is information, not decoration. */

/* ── Soft ─────────────────────────────────────────────────────────────── */
[data-shape="soft"] :is(.lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) {
  box-shadow: inset 0 1px 0 0 color-mix(in srgb, #fff 18%, transparent),
    0 18px 40px -30px color-mix(in srgb, var(--brand) 55%, transparent);
}

/* ── Fluctlight ───────────────────────────────────────────────────────────
   A lightcube, not a console. The resting face is a rim of light along the
   top that is brightest in the middle and a small constellation of motes
   settled in the upper-right corner -- the same motes the entrance releases,
   caught at rest. The old face was two 110px inset glows down both sides;
   in the light readings they turned into a tan stain on every card. */
[data-shape="fluctlight"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) {
  background-image:
    linear-gradient(90deg, transparent 6%, color-mix(in oklab, var(--brand-deep) 80%, transparent) 50%, transparent 94%),
    radial-gradient(circle at calc(100% - 38px) 22px, color-mix(in oklab, var(--brand-deep) 90%, transparent) 0 1.3px, transparent 2px),
    radial-gradient(circle at calc(100% - 62px) 14px, color-mix(in oklab, var(--brand) 75%, transparent) 0 1px, transparent 1.6px),
    radial-gradient(circle at calc(100% - 24px) 44px, color-mix(in oklab, var(--gold, var(--brand)) 70%, transparent) 0 1px, transparent 1.5px),
    radial-gradient(circle at calc(100% - 84px) 30px, color-mix(in oklab, var(--brand-deep) 55%, transparent) 0 .9px, transparent 1.4px),
    radial-gradient(circle at calc(100% - 50px) 52px, color-mix(in oklab, var(--brand) 45%, transparent) 0 .8px, transparent 1.3px),
    radial-gradient(90% 70% at 100% 0%, color-mix(in oklab, var(--brand-deep) 11%, transparent), transparent 70%);
  background-repeat: no-repeat;
  background-size: 100% 1px, auto, auto, auto, auto, auto, auto;
  background-position: 0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0;
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--brand-deep) 34%, transparent),
    0 0 0 1px color-mix(in oklab, var(--brand) 8%, transparent),
    0 22px 48px -34px color-mix(in oklab, var(--brand-deep) 80%, transparent);
}
[data-shape="fluctlight"] .card:hover,
[data-shape="fluctlight"] :is(.lwhat-card, .lterm, .lmodel-gate, .lstat):hover {
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--brand-deep) 62%, transparent),
    0 0 0 1px color-mix(in oklab, var(--brand) 16%, transparent),
    0 0 34px -14px var(--brand-deep);
  filter: none;
}
/* Light readings: light is drawn by what is behind it. On a pale page the
   constellation darkens to ink and the corner bloom goes. */
[data-shape="fluctlight"][data-theme="light"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) {
  box-shadow: inset 0 0 0 1px color-mix(in oklab, var(--brand-deep) 26%, transparent),
    0 18px 40px -30px color-mix(in oklab, var(--brand-deep) 40%, transparent);
}

/* ── Frame ────────────────────────────────────────────────────────────────
   A tactical HUD. Brackets were hover-only; a HUD's brackets are the one
   thing it never hides. They stand at rest now, and a calibration ruler runs
   along the top-right edge -- the marks a targeting overlay carries. Hover
   still grows the brackets, as it did. */
[data-shape="frame"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) {
  background-image:
    linear-gradient(90deg, var(--brand-deep) 0 100%), linear-gradient(180deg, var(--brand-deep) 0 100%),
    linear-gradient(90deg, var(--brand-deep) 0 100%), linear-gradient(180deg, var(--brand-deep) 0 100%),
    linear-gradient(90deg, var(--brand-deep) 0 100%), linear-gradient(180deg, var(--brand-deep) 0 100%),
    linear-gradient(90deg, var(--brand-deep) 0 100%), linear-gradient(180deg, var(--brand-deep) 0 100%),
    repeating-linear-gradient(90deg, color-mix(in srgb, var(--brand-deep) 70%, transparent) 0 1px, transparent 1px 7px);
  background-repeat: no-repeat;
  background-position: 0 0, 0 0, 100% 0, 100% 0, 0 100%, 0 100%, 100% 100%, 100% 100%, calc(100% - 22px) 7px;
  background-size: 11px 1.5px, 1.5px 11px, 11px 1.5px, 1.5px 11px, 11px 1.5px, 1.5px 11px, 11px 1.5px, 1.5px 11px, 71px 5px;
}
[data-shape="frame"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat):hover {
  background-size: 18px 2px, 2px 18px, 18px 2px, 2px 18px, 18px 2px, 2px 18px, 18px 2px, 2px 18px, 71px 5px;
}

/* ── Blade ────────────────────────────────────────────────────────────────
   The drawn sword. One corner is cut, on a diagonal, and the cut is lit --
   the only chamfer in the set that is asymmetric, because a blade cuts once.
   The top edge is the polished edge: a line that is brightest where the cut
   begins and fades back toward the hilt, with a short guard at the left.
   Hover runs light along that edge, the way the buttons already slash. */
[data-shape="blade"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) {
  clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 0 100%);
  background-image:
    linear-gradient(90deg, transparent 0, color-mix(in srgb, var(--brand-deep) 30%, transparent) 40%, var(--brand) calc(100% - 22px), transparent calc(100% - 22px)),
    linear-gradient(225deg, transparent calc(50% - 1px), var(--brand) calc(50% - 1px) calc(50% + .5px), transparent calc(50% + .5px)),
    linear-gradient(90deg, transparent 0, color-mix(in srgb, #fff 55%, transparent) 50%, transparent 100%),
    linear-gradient(180deg, var(--brand) 0 100%);
  background-repeat: no-repeat;
  background-size: 100% 1.5px, 22px 22px, 30% 1.5px, 2.5px 26px;
  background-position: 0 0, 100% 0, -60% 0, 0 14px;
}
/* A transition, not an animation: swapping the animation property on hover
   would hand it back to shape-blade-in on mouse-out and re-cut the card open
   every time the pointer left it. The transition lives on the hover state
   only, so the light runs out along the edge and snaps home unseen. */
[data-shape="blade"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat):hover {
  background-position: 0 0, 100% 0, 160% 0, 0 14px;
  transition: background-position .7s cubic-bezier(.3, .7, .4, 1), box-shadow .16s linear;
}

/* ── Cardinal ─────────────────────────────────────────────────────────────
   The original console. It already cut two corners; what it lacked was the
   line along the cut, so at rest it read as a box with bites out of it. Now
   the chamfers are lined like the plate's edge, and the two square corners
   carry a rivet -- a plate bolted to a frame, which is what that console was. */
[data-shape="cardinal"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) {
  clip-path: polygon(15px 0, 100% 0, 100% calc(100% - 15px), calc(100% - 15px) 100%, 0 100%, 0 15px);
  border-color: transparent;
  background-image:
    linear-gradient(135deg, transparent calc(50% - 1px), var(--brand-deep) calc(50% - 1px) calc(50% + .6px), transparent calc(50% + .6px)),
    linear-gradient(135deg, transparent calc(50% - .6px), var(--brand-deep) calc(50% - .6px) calc(50% + 1px), transparent calc(50% + 1px)),
    linear-gradient(var(--brand-deep) 0 0), linear-gradient(var(--brand-deep) 0 0);
  background-repeat: no-repeat;
  background-size: 15px 15px, 15px 15px, 4px 4px, 4px 4px;
  background-position: 0 0, 100% 100%, calc(100% - 7px) 7px, 7px calc(100% - 7px);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--brand-deep) 55%, transparent);
}
[data-shape="cardinal"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat):hover {
  box-shadow: inset 0 0 0 1px var(--brand-deep), inset 0 0 22px -12px var(--brand-deep);
  filter: none;
}

/* ── Cardinal 2.0 ─────────────────────────────────────────────────────────
   The console rebuilt, and the one Chris described as "based on the system
   design": a pale title plate across the head of every panel with a rule
   under it, the brand rail riding the plate's top edge, and one clipped
   corner at the foot. The plate is what makes it a *system* window rather
   than a card -- the part the title sits in is a different material from
   the part the content sits in. */
[data-shape="cardinal2"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) {
  background-image:
    linear-gradient(90deg, var(--brand-deep) 0 100%),
    linear-gradient(90deg, color-mix(in srgb, #fff 85%, transparent) 0 100%),
    linear-gradient(90deg, color-mix(in srgb, var(--text-primary) 16%, transparent) 0 100%),
    linear-gradient(180deg, color-mix(in srgb, var(--text-primary) 7%, transparent), color-mix(in srgb, var(--text-primary) 4%, transparent));
  background-repeat: no-repeat;
  background-size: 44% 2px, 30px 2px, 100% 1px, 100% 52px;
  background-position: 0 0, 100% 0, 0 52px, 0 0;
}
[data-shape="cardinal2"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat):hover {
  background-size: 100% 2px, 30px 2px, 100% 1px, 100% 52px;
}
/* A plate of fixed height is wrong the moment a header holds a control: the
   rule ran straight through the threshold filter on the model page. So where a
   panel has a real header, the plate IS the header -- bled out to the card's
   edges by the card's own padding, however tall its contents -- and the card
   itself drops its copy. Landing plates open on a figure or a short label and
   keep the rails without the plate. */
[data-shape="cardinal2"] .card { --c2-pt: 24px; --c2-px: 26px; }
[data-shape="cardinal2"] .card.hero { --c2-pt: 30px; --c2-px: 30px; }
@media (max-width: 900px) {
  [data-shape="cardinal2"] .card { --c2-pt: 20px; --c2-px: 20px; }
  [data-shape="cardinal2"] .card.hero { --c2-pt: 24px; --c2-px: 22px; }
}
@media (max-width: 600px) {
  [data-shape="cardinal2"] .card { --c2-pt: 17px; --c2-px: 17px; }
}
[data-shape="cardinal2"] .card:has(> .il-panel-head) { background-image: none; }
[data-shape="cardinal2"] .card > .il-panel-head {
  margin: calc(var(--c2-pt) * -1) calc(var(--c2-px) * -1) 16px;
  padding: 15px var(--c2-px) 13px;
  align-items: center;
  background-image:
    linear-gradient(90deg, var(--brand-deep) 0 100%),
    linear-gradient(90deg, color-mix(in srgb, #fff 85%, transparent) 0 100%),
    linear-gradient(180deg, color-mix(in srgb, var(--text-primary) 7%, transparent), color-mix(in srgb, var(--text-primary) 3.5%, transparent));
  background-repeat: no-repeat;
  background-size: 44% 2px, 30px 2px, 100% 100%;
  background-position: 0 0, 100% 0, 0 0;
  border-bottom: 1px solid color-mix(in srgb, var(--text-primary) 16%, transparent);
  transition: background-size .3s cubic-bezier(.2, .9, .25, 1);
}
[data-shape="cardinal2"] .card:hover > .il-panel-head { background-size: 100% 2px, 30px 2px, 100% 100%; }
[data-shape="cardinal2"] :is(.lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) {
  background-size: 44% 2px, 30px 2px, 0 0, 0 0;
}
[data-shape="cardinal2"] :is(.lwhat-card, .lterm, .lmodel-gate, .lstat):hover {
  background-size: 100% 2px, 30px 2px, 0 0, 0 0;
}

/* ── System ───────────────────────────────────────────────────────────────
   The Player's window: a pane of light. It had the brackets and the twin
   rails; what it lacked was the light itself. A hologram carries scanlines
   and a halo, and the window's top edge is a bar of light brightest at the
   centre, where the title of a notification sits. */
[data-shape="system"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) {
  background-image:
    linear-gradient(90deg, var(--brand-deep) 0 100%), linear-gradient(180deg, var(--brand-deep) 0 100%),
    linear-gradient(90deg, var(--brand-deep) 0 100%), linear-gradient(180deg, var(--brand-deep) 0 100%),
    linear-gradient(90deg, var(--brand-deep) 0 100%), linear-gradient(180deg, var(--brand-deep) 0 100%),
    linear-gradient(90deg, var(--brand-deep) 0 100%), linear-gradient(180deg, var(--brand-deep) 0 100%),
    linear-gradient(90deg, transparent 8%, color-mix(in oklab, var(--brand-deep) 95%, #fff) 50%, transparent 92%),
    repeating-linear-gradient(180deg, color-mix(in oklab, var(--brand-deep) 7%, transparent) 0 1px, transparent 1px 4px);
  background-repeat: no-repeat;
  background-position: 0 0, 0 0, 100% 0, 100% 0, 0 100%, 0 100%, 100% 100%, 100% 100%, 0 0, 0 0;
  background-size: 17px 2px, 2px 17px, 17px 2px, 2px 17px, 17px 2px, 2px 17px, 17px 2px, 2px 17px, 100% 2px, 100% 100%;
}
[data-shape="system"] :is(.lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) {
  box-shadow: inset 3px 0 0 0 var(--brand-deep), inset -3px 0 0 0 var(--brand-deep),
    inset 0 0 0 1px color-mix(in oklab, var(--brand-deep) 24%, transparent),
    0 0 30px -13px var(--brand-deep);
}

/* ── The panel title marker ───────────────────────────────────────────────
   Every panel labels itself in small mono caps; each system marks its titles
   differently, and that mark is the cheapest place for a shape to speak in
   every panel at once. The title's ::before is free (the head and the h3
   carry no pseudo-elements anywhere else). */
[data-il-panel] > .il-panel-head h3::before {
  content: ""; display: inline-block; vertical-align: 1px; margin-right: 9px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--brand);
}
[data-shape="fluctlight"] [data-il-panel] > .il-panel-head h3::before {
  width: 5px; height: 5px; border-radius: 1px; transform: rotate(45deg);
  background: var(--brand-deep);
  box-shadow: 0 0 8px 1px color-mix(in oklab, var(--brand-deep) 70%, transparent);
}
[data-shape="frame"] [data-il-panel] > .il-panel-head h3::before {
  width: 6px; height: 6px; border-radius: 0; background: none;
  border: 1.5px solid var(--brand-deep);
}
[data-shape="blade"] [data-il-panel] > .il-panel-head h3::before {
  width: 12px; height: 3px; border-radius: 0; background: var(--brand);
  transform: skewX(-38deg);
}
[data-shape="cardinal"] [data-il-panel] > .il-panel-head h3::before {
  width: 6px; height: 6px; border-radius: 0; background: var(--brand-deep);
}
[data-shape="cardinal2"] [data-il-panel] > .il-panel-head h3::before {
  width: 3px; height: 11px; vertical-align: -1px; border-radius: 0; background: var(--brand-deep);
}
[data-shape="system"] [data-il-panel] > .il-panel-head h3::before {
  content: "!"; width: 13px; height: 13px; line-height: 12px; vertical-align: 0;
  border-radius: 0; background: none; text-align: center;
  font-size: 9.5px; font-weight: 700; letter-spacing: 0; color: var(--brand-deep);
  border: 1px solid var(--brand-deep);
  box-shadow: 0 0 9px -2px var(--brand-deep), inset 0 0 6px -3px var(--brand-deep);
}

/* The same marker on the landing's section eyebrows, so the playground's
   shape choice reads in the page's own headings as well as its panels. */
.landing .lsection > .eyebrow::before, .landing .lplay-copy > .eyebrow::before,
.landing .lhero-copy > .eyebrow::before {
  content: ""; display: inline-block; vertical-align: 1px; margin-right: 10px;
  width: 5px; height: 5px; border-radius: 50%; background: var(--brand);
}
[data-shape="fluctlight"] .landing :is(.lsection, .lplay-copy, .lhero-copy) > .eyebrow::before {
  border-radius: 1px; transform: rotate(45deg); background: var(--brand-deep);
  box-shadow: 0 0 8px 1px color-mix(in oklab, var(--brand-deep) 70%, transparent);
}
[data-shape="frame"] .landing :is(.lsection, .lplay-copy, .lhero-copy) > .eyebrow::before {
  width: 6px; height: 6px; border-radius: 0; background: none; border: 1.5px solid var(--brand-deep);
}
[data-shape="blade"] .landing :is(.lsection, .lplay-copy, .lhero-copy) > .eyebrow::before {
  width: 14px; height: 3px; border-radius: 0; transform: skewX(-38deg);
}
[data-shape="cardinal"] .landing :is(.lsection, .lplay-copy, .lhero-copy) > .eyebrow::before {
  width: 6px; height: 6px; border-radius: 0; background: var(--brand-deep);
}
[data-shape="cardinal2"] .landing :is(.lsection, .lplay-copy, .lhero-copy) > .eyebrow::before {
  width: 3px; height: 11px; vertical-align: -1px; border-radius: 0; background: var(--brand-deep);
}
[data-shape="system"] .landing :is(.lsection, .lplay-copy, .lhero-copy) > .eyebrow::before {
  content: "!"; width: 13px; height: 13px; line-height: 12px; vertical-align: 0;
  border-radius: 0; background: none; text-align: center;
  font-size: 9.5px; font-weight: 700; letter-spacing: 0; color: var(--brand-deep);
  border: 1px solid var(--brand-deep);
  box-shadow: 0 0 9px -2px var(--brand-deep);
}

@media (prefers-reduced-motion: reduce) {
  :root:not([data-motion-choice="user"])[data-shape="blade"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat):hover {
    transition: none;
  }
}

/* ── Entrances that end where the shape rests ─────────────────────────────
   Blade's entrance wiped in with `inset()` and its resting face is a polygon
   with one corner cut, so the last frame snapped from a rectangle to the cut.
   Both keyframes are redefined here (the later definition of a name wins) as
   polygons of the same five points, which interpolate: the blade draws in
   from the left and arrives already cut. `--cut` is 0 on anything that rests
   square -- rows, drawers -- so they wipe in exactly as before. */
[data-shape="blade"] { --cut: 0px; }
[data-shape="blade"] :is(.card, .lwhat-card, .lterm, .lmodel-gate, .lstat, .lplay-panel, .lhv-card) { --cut: 22px; }
@keyframes shape-blade-in {
  0%   { clip-path: polygon(0 0, 0 0, 0 var(--cut), 0 100%, 0 100%); opacity: .2;
         box-shadow: inset -3px 0 0 0 var(--brand-deep); }
  22%  { opacity: 1; }
  92%  { box-shadow: inset -3px 0 0 0 var(--brand-deep); }
  100% { clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%);
         opacity: 1; box-shadow: inset 0 0 0 0 transparent; }
}
@keyframes il-blade-cut {
  0%   { opacity: 0; clip-path: polygon(0 0, 0 0, 0 var(--cut), 0 100%, 0 100%); }
  70%  { opacity: 1; clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%); }
  100% { opacity: 1; clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%); }
}

/* Fluctlight condenses; it does not boot. il-design-bridge.css rewrote this
   shape's entrance to gather out of a bloom -- "nothing snaps, nothing
   flickers, nothing scans", after Chris: fluctlight is "more inspired by
   particles and the world" -- but cards kept style.css's older
   `shape-flc-in`: a wipe from the centre, two opacity dips and a sideways
   jitter, which is System's grammar. Cards now take the condensing entrance
   everything else in this shape already uses. */
[data-shape="fluctlight"] .card {
  animation-name: il-flc-boot;
  animation-duration: .78s;
}

/* ── Focus survives the shape ─────────────────────────────────────────────
   style.css draws a focused button's ring as a box-shadow outside it, and it
   was being erased in two ways. `.btn.primary` sets its own box-shadow at the
   same specificity, later in the file, so a focused primary button -- the
   "+ Invest", the "Run screen" -- showed nothing in any shape. And Cardinal,
   Cardinal 2.0 and System clip their buttons to a polygon, which clips
   everything outside it, so in those three shapes no button showed focus at
   all. Measured by tabbing the Overview in all seven shapes and reading each
   focused element's computed ring.

   So the ring is drawn inside the button, where no clip reaches: a line in the
   brand on an ordinary button, and in the page's own colour on a filled one,
   where brand on brand would vanish. The soft halo outside stays wherever the
   shape lets it show. Keyboard only (:focus-visible), and above the shapes'
   own button rules, which set box-shadow for their hover grammar. */
:root[data-shape] .btn:focus-visible {
  outline: none;
  box-shadow: inset 0 0 0 2px var(--brand), 0 0 0 3px color-mix(in srgb, var(--brand) 32%, transparent);
}
:root[data-shape] .btn.primary:focus-visible {
  box-shadow: inset 0 0 0 2px var(--plane), 0 0 0 3px color-mix(in srgb, var(--brand) 45%, transparent);
}
/* The Overview's company tiles are focusable and marked focus only by a
   1px border shifting towards the brand -- their hover. */
:root .sc-card:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
