/* ==========================================================================
   CYPRUS COMIC CON 2026: article design system
   --------------------------------------------------------------------------
   Loaded AFTER global.css. Every rule is scoped under .ccc (the article
   wrapper) or .ccc-* so nothing reaches the injected header, the injected
   footer, the contact block, or the floating shapes.

   THE TWO PALETTES. This page carries two, and the split is the whole
   design:

   - The PAGE follows the site. Ground is body's --blue (#6EC1E4), which
     this file leaves alone rather than painting over; prose and headings
     are the global --dark (#2B4080), which news.css already reaches for
     and labels "more readable"; cards are the site's glass
     (rgba(255,255,255,0.1) at a 20px radius) and figure heads sit on it.

   - A MOUNT is any dark surface the page shows something on: a canvas of
     pixel art, a chartool screenshot, the code listing, a live equation,
     and the controls belonging to any of them. Those keep the trailer's
     own palette (--ccc-m-*), because the art is indexed colour built for a
     black ground and reads on nothing else. news.css mounts a post's video
     on rgba(0, 0, 0, 0.3) for the same reason, so this is the site's own
     habit rather than an exception to it.

   The boundary is structural, not a list: .ccc-viz > *:not(.ccc-viz-head)
   takes the mount ground, so a figure that grows a new child gets it right
   without this file being told. ccc26-*.js draws with the --ccc-m-* set,
   read off .ccc through CCC26._cssVar, so a canvas can never pick up a page
   colour by accident.

   Three further judgement calls, recorded so they are not re-litigated:

   1. NO gradients, no soft glow, no drop shadows INSIDE a mount. The
      subject is indexed colour with hard tonal steps; a soft radial wash is
      the exact "photograph of pixel art" tell the copy attacks. Mounts keep
      hard edges (--ccc-r-px is 0) while cards take the site's 20px, because
      a 20px radius on a canvas of 32x37 pixel art reads as a rounded
      television.

   2. --ccc-deep is NOT an alternator. .ccc-section--alt carries hairline
      top and bottom edges, which is what makes the ground change legible,
      and is meant for a section that is one exhibit (a gallery) rather
      than for alternation.

   3. Accent economy, one job each, within each palette: --ccc-hot is the
      section number, --ccc-gold is numbers and nothing else, --ccc-accent
      is links and focus. That is what leaves a gold readout still able to
      catch the eye.
   ========================================================================== */

.ccc {
    /* Ground and ink. Every value is a real colour from the trailer's own
       66-entry master palette (D:/CCC26_Pixel/engine/palette.py). */
    --ccc-deep:      rgba(255, 255, 255, 0.16); /* alternating section ground */
    --ccc-panel:     rgba(255, 255, 255, 0.10); /* glass card, per news.css */
    --ccc-line:      rgba(255, 255, 255, 0.22); /* glass edge, hairlines */
    --ccc-dim:       rgba(29, 43, 87, 0.70);    /* captions, secondary text */
    --ccc-text:      #2B4080;   /* global `--dark`, news.css's readable body */
    --ccc-bright:    #1D2B57;   /* headings, a step deeper than body */
    --ccc-accent:    #2B4080;   /* links and focus: 4.8:1 on the blue ground */
    --ccc-hot:       #E91E63;   /* global magenta, the section number */
    --ccc-gold:      #FFD700;   /* global yellow */
    --ccc-on-accent: #f2f2f2;   /* global `--text`, on any accent fill */

    /* Mount palette. A mount is a dark surface the page shows something on:
       a canvas of pixel art, a chartool screenshot, the code listing, a live
       equation. The trailer's art is indexed colour built for a black ground
       and only reads on one, and news.css already mounts a post's video on
       rgba(0, 0, 0, 0.3), so these keep the trailer's palette while the page
       around them follows the site. ccc26-*.js draws with these, reading them
       off .ccc through CCC26._cssVar. */
    --ccc-m-void:   #0B0B12;
    --ccc-m-panel:  #1C1B26;
    --ccc-m-line:   #2E2C3E;
    --ccc-m-dim:    #8E8BA3;
    --ccc-m-text:   #D7D4E2;
    --ccc-m-bright: #F4F2FA;
    --ccc-m-accent: #5FD6E2;
    --ccc-m-gold:   #FFD24A;
    --ccc-m-hot:    #E03DA8;
    --ccc-m-on-accent: #0B0B12;
    --ccc-m-ring:   rgba(95, 214, 226, 0.28);

    /* Hard-edged accent ring, used for hover and press on controls. */
    --ccc-ring: rgba(43, 64, 128, 0.28);

    /* Spacing scale. Nothing off it, with one declared exception: the
       mobile gutter is 20px, matching the rest of the site. */
    --ccc-s4:  4px;
    --ccc-s8:  8px;
    --ccc-s12: 12px;
    --ccc-s16: 16px;
    --ccc-s24: 24px;
    --ccc-s32: 32px;
    --ccc-s48: 48px;
    --ccc-s64: 64px;
    --ccc-s96: 96px;

    /* Radius is a hard split, not a preference: a rounded corner on a
       384x216 indexed image is a lie about the medium. */
    --ccc-r-px: 0;
    --ccc-r-card: 20px;         /* news.css's card radius */
    --ccc-r-ui: 6px;

    /* Structural */
    --ccc-header:  120px;   /* global.css fixed header, desktop and mobile */
    /* The measure is px, NOT ch. `ch` resolves against each element's own
       font-size, so a 72px h1 and a 14px caption sharing `max-width: 68ch`
       get columns 3480px and 571px wide and no two blocks in the article
       line up. 640px is ~72 characters of Inter at the body size. */
    --ccc-measure: 640px;
    --ccc-wide:    1180px;

    --ccc-font: 'Inter', sans-serif;
    --ccc-mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, 'Cascadia Mono', Menlo, Consolas, monospace;

    --ccc-motion: 140ms;
    --ccc-ease: ease-out;

    display: block;
    position: relative;
    width: 100%;
    background: transparent;
    color: var(--ccc-text);
    font-family: var(--ccc-font);
    font-weight: 400;
    font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
    line-height: 1.65;
    overflow-x: clip;
}

/* --------------------------------------------------------------------------
   Pixel rendering. First rule to check: without it the whole page is
   pointless. Opt-in, so the one chart canvas stays smoothed by default.
   -------------------------------------------------------------------------- */

.ccc .ccc-px {
    image-rendering: -webkit-optimize-contrast;
    image-rendering: -moz-crisp-edges;
    image-rendering: crisp-edges;
    image-rendering: pixelated;
    /* Pixel art is never scaled down to fit: it holds its integer multiple
       and its container scrolls instead. */
    max-width: none;
}

.ccc img {
    display: block;
    max-width: 100%;
    height: auto;
}

.ccc canvas {
    display: block;
}

/* --------------------------------------------------------------------------
   Base prose
   -------------------------------------------------------------------------- */

.ccc p {
    max-width: var(--ccc-measure);
}

.ccc strong {
    color: var(--ccc-bright);
    font-weight: 700;
}

.ccc em {
    font-style: italic;
}

.ccc code {
    font-family: var(--ccc-mono);
    font-weight: 500;
    font-size: 0.9em;
    color: var(--ccc-bright);
}

.ccc a {
    color: var(--ccc-accent);
    text-decoration: underline;
    text-underline-offset: 3px;
    text-decoration-thickness: 1px;
    transition: color var(--ccc-motion) var(--ccc-ease);
}

.ccc a:hover {
    color: var(--ccc-bright);
}

/* Every interactive element, without exception. */
.ccc :focus-visible {
    outline: 2px solid var(--ccc-accent);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.ccc .ccc-hero {
    padding: calc(var(--ccc-header) + var(--ccc-s48)) var(--ccc-s24) var(--ccc-s96);
}

.ccc .ccc-eyebrow {
    display: block;
    font-family: var(--ccc-mono);
    font-weight: 600;
    font-size: 0.875rem;
    line-height: 1.4;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--ccc-accent);
    margin-bottom: var(--ccc-s16);
}

.ccc .ccc-title {
    font-family: var(--ccc-font);
    font-weight: 900;
    font-size: clamp(2.25rem, 1.5rem + 3vw, 4.5rem);
    line-height: 0.95;
    letter-spacing: -0.03em;
    color: var(--ccc-bright);
    margin-bottom: var(--ccc-s32);
}

/* Larger type, same column: the measure narrows in characters as the type
   grows, which is what a standfirst wants, and every block in the article
   keeps one left edge. */
.ccc .ccc-standfirst {
    font-size: clamp(1.125rem, 1.05rem + 0.35vw, 1.375rem);
    line-height: 1.5;
    color: var(--ccc-text);
}

.ccc .ccc-standfirst p {
    max-width: inherit;
}

.ccc .ccc-standfirst p + p {
    margin-top: var(--ccc-s24);
}

/* --------------------------------------------------------------------------
   Trailer. The class name here is deliberately .ccc-trailer and must never
   be the news-post hero class that assets/js/news.js binds loadPost() to:
   that script is not loaded on this page and would throw on an empty
   videos array.
   -------------------------------------------------------------------------- */

.ccc .ccc-trailer {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 9;
    background: var(--ccc-m-panel);
    border: 1px solid var(--ccc-m-line);
    border-radius: var(--ccc-r-px);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
}

.ccc .ccc-trailer-label {
    font-family: var(--ccc-mono);
    font-weight: 500;
    font-size: 0.875rem;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    text-align: center;
    color: var(--ccc-m-dim);
    padding: var(--ccc-s24);
}

.ccc .ccc-trailer iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
}

/* --------------------------------------------------------------------------
   Sections and vertical rhythm

   Within a group: 12 / 16 / 24. Between groups: 32 / 48. Between
   sections: 96. Adjacent block margins collapse, so a block object
   following a paragraph lands on 48, not 72.
   -------------------------------------------------------------------------- */

.ccc .ccc-section {
    padding: var(--ccc-s96) var(--ccc-s24);
}

/* global.css fixes the header, so an in-page jump (section 02 links to
   section 13) would otherwise land with the heading behind it. */
.ccc [id] {
    scroll-margin-top: calc(var(--ccc-header) + var(--ccc-s24));
}

.ccc .ccc-section--alt {
    background: var(--ccc-deep);
    border-top: 1px solid var(--ccc-line);
    border-bottom: 1px solid var(--ccc-line);
}

.ccc .ccc-hero > *,
.ccc .ccc-section > * {
    max-width: var(--ccc-measure);
    margin-left: auto;
    margin-right: auto;
}

.ccc .ccc-hero > .ccc-trailer,
.ccc .ccc-hero > .ccc-viz,
.ccc .ccc-hero > .ccc-strip-scroll,
.ccc .ccc-section > .ccc-trailer,
.ccc .ccc-section > .ccc-viz,
.ccc .ccc-section > .ccc-strip-scroll,
.ccc .ccc-section > .ccc-plate--wide,
.ccc .ccc-section > .ccc-fig:has(.ccc-plate--wide),
.ccc .ccc-section > .ccc-fig:has(.ccc-strip-scroll) {
    max-width: var(--ccc-wide);
}

.ccc .ccc-hero > :first-child,
.ccc .ccc-section > :first-child {
    margin-top: 0;
}

.ccc .ccc-hero > :last-child,
.ccc .ccc-section > :last-child {
    margin-bottom: 0;
}

.ccc .ccc-section > p {
    margin-bottom: var(--ccc-s24);
}

/* Block objects sit a full group away from the prose around them. */
.ccc .ccc-trailer,
.ccc .ccc-viz,
.ccc .ccc-fig,
.ccc .ccc-plate,
.ccc .ccc-strip-scroll {
    margin-top: var(--ccc-s48);
    margin-bottom: var(--ccc-s48);
}

/* A note belongs to the object above it, so it hugs rather than floats. */
.ccc .ccc-trailer:has(+ .ccc-note),
.ccc .ccc-fig:has(+ .ccc-note),
.ccc .ccc-plate:has(+ .ccc-note),
.ccc .ccc-strip-scroll:has(+ .ccc-note) {
    margin-bottom: var(--ccc-s16);
}

/* --------------------------------------------------------------------------
   Headings and section text
   -------------------------------------------------------------------------- */

.ccc .ccc-kicker {
    display: block;
    font-family: var(--ccc-mono);
    font-weight: 600;
    font-size: 0.875rem;
    line-height: 1.4;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--ccc-hot);
    margin-bottom: var(--ccc-s12);
}

.ccc .ccc-h2 {
    font-family: var(--ccc-font);
    font-weight: 700;
    font-size: clamp(1.5rem, 1.3rem + 0.9vw, 2.25rem);
    line-height: 1.15;
    letter-spacing: -0.02em;
    color: var(--ccc-bright);
    margin-bottom: var(--ccc-s24);
}

.ccc .ccc-h3 {
    font-family: var(--ccc-font);
    font-weight: 700;
    font-size: 1.25rem;
    line-height: 1.3;
    letter-spacing: -0.01em;
    color: var(--ccc-bright);
    margin-top: var(--ccc-s48);
    margin-bottom: var(--ccc-s16);
}

.ccc .ccc-lede {
    font-size: clamp(1.125rem, 1.05rem + 0.3vw, 1.3125rem);
    line-height: 1.5;
    color: var(--ccc-bright);
    margin-bottom: var(--ccc-s32);
}

/* The rule sits on the column's left edge and the text is inset from it;
   the extra right inset keeps the aside's own measure near the body's
   without pulling its left edge off the column. */
.ccc .ccc-note {
    font-size: 0.9rem;
    line-height: 1.6;
    color: var(--ccc-dim);
    border-left: 1px solid var(--ccc-line);
    padding-left: var(--ccc-s16);
    padding-right: var(--ccc-s64);
    margin-top: var(--ccc-s16);
    margin-bottom: var(--ccc-s24);
}

/* --------------------------------------------------------------------------
   Figures and plates
   -------------------------------------------------------------------------- */

.ccc .ccc-fig {
    display: block;
    width: 100%;
}

.ccc .ccc-fig-cap {
    display: block;
    max-width: var(--ccc-measure);
    margin: var(--ccc-s16) auto 0;
    font-family: var(--ccc-mono);
    font-weight: 500;
    font-size: 0.875rem;
    line-height: 1.7;
    color: var(--ccc-dim);
}

.ccc .ccc-plate {
    display: flex;
    flex-direction: column;
    align-items: center;
    /* `safe` is what makes the centring survive overflow. Plain `center` on a
       scroll container pushes the content's leading edge outside the box,
       where scrollLeft: 0 already sits past it and no amount of scrolling
       reaches it: a 768px still in a 640px plate loses its left half
       permanently. `safe` falls back to start alignment the moment the
       content would overflow. The unprefixed line above is the fallback for
       engines that do not parse the keyword. */
    align-items: safe center;
    gap: var(--ccc-s16);
    background: var(--ccc-m-panel);
    border: 1px solid var(--ccc-m-line);
    border-radius: var(--ccc-r-px);
    padding: var(--ccc-s24);
    max-width: 100%;
    /* Pixel art holds its integer scale; the mount scrolls if it must. One
       axis only: `overflow-x` alone computes `overflow-y` to `auto` as well,
       which makes every plate a two-axis scroller. */
    overflow-x: auto;
    overflow-y: hidden;
}

/* Inside a <figure> the caption is the block object's own label, so the
   figure carries the rhythm and the plate hugs the caption. */
.ccc .ccc-fig > .ccc-plate,
.ccc .ccc-fig > .ccc-strip-scroll {
    margin-top: 0;
    margin-bottom: 0;
}

.ccc .ccc-plate--wide {
    width: 100%;
}

.ccc .ccc-plate .ccc-fig-cap {
    text-align: center;
}

/* A figure nested inside a plate is one item of a scrolling row (the sponsor
   plates); its label is a single line of metrics and wrapping it on the
   narrowest plate breaks the row's baseline. The row already scrolls. */
.ccc .ccc-plate .ccc-fig > .ccc-fig-cap {
    white-space: nowrap;
}

/* --------------------------------------------------------------------------
   Horizontal scroll containers. The page body must never scroll
   horizontally, so anything wider than the viewport scrolls inside one of
   these, with a scrollbar that is visible and wide enough to grab.
   -------------------------------------------------------------------------- */

.ccc .ccc-strip-scroll {
    max-width: 100%;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-color: var(--ccc-m-line) var(--ccc-m-void);
    scrollbar-width: auto;
}

.ccc .ccc-strip-scroll::-webkit-scrollbar,
.ccc .ccc-viz-stage::-webkit-scrollbar,
.ccc .ccc-code::-webkit-scrollbar,
.ccc .ccc-eq::-webkit-scrollbar {
    width: 12px;
    height: 12px;
}

.ccc .ccc-strip-scroll::-webkit-scrollbar-track,
.ccc .ccc-viz-stage::-webkit-scrollbar-track,
.ccc .ccc-code::-webkit-scrollbar-track,
.ccc .ccc-eq::-webkit-scrollbar-track {
    background: var(--ccc-m-void);
    border: 1px solid var(--ccc-m-line);
}

.ccc .ccc-strip-scroll::-webkit-scrollbar-thumb,
.ccc .ccc-viz-stage::-webkit-scrollbar-thumb,
.ccc .ccc-code::-webkit-scrollbar-thumb,
.ccc .ccc-eq::-webkit-scrollbar-thumb {
    background: var(--ccc-m-line);
    border-radius: var(--ccc-r-px);
}

.ccc .ccc-strip-scroll::-webkit-scrollbar-thumb:hover,
.ccc .ccc-viz-stage::-webkit-scrollbar-thumb:hover,
.ccc .ccc-code::-webkit-scrollbar-thumb:hover,
.ccc .ccc-eq::-webkit-scrollbar-thumb:hover {
    background: var(--ccc-m-dim);
}

/* --------------------------------------------------------------------------
   Visualisation blocks

   The stage is recessed rather than raised: --ccc-m-void inside the glass card,
   so the canvas reads as cut into the block.
   -------------------------------------------------------------------------- */

.ccc .ccc-viz {
    width: 100%;
    background: var(--ccc-panel);
    backdrop-filter: blur(10px);
    border: 1px solid var(--ccc-line);
    border-radius: var(--ccc-r-card);
    /* The stage, the controls and a live equation form one dark instrument
       running to the bottom of the card, so the card clips them to its own
       corners rather than each needing to know where it sits in the stack. */
    overflow: hidden;
}

/* The head is the only part of a figure that sits on the page. Everything
   below it is the instrument, so it takes the mount ground by structure
   rather than by enumeration: a block that grows a new child (the codebase
   map, the tool tour) gets the right ground without this file being told. */
.ccc .ccc-viz > *:not(.ccc-viz-head) {
    background: var(--ccc-m-void);
}

.ccc .ccc-viz-head {
    display: flex;
    flex-direction: column;
    gap: var(--ccc-s8);
    padding: var(--ccc-s16) var(--ccc-s24);
    border-bottom: 1px solid var(--ccc-line);
}

.ccc .ccc-viz-title,
.ccc .ccc-viz-head h2,
.ccc .ccc-viz-head h3,
.ccc .ccc-viz-head h4 {
    margin: 0;
    font-family: var(--ccc-mono);
    font-weight: 600;
    font-size: 0.875rem;
    line-height: 1.4;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--ccc-accent);
}

.ccc .ccc-viz-hint,
.ccc .ccc-viz-head p {
    margin: 0;
    max-width: 60ch;
    font-family: var(--ccc-font);
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--ccc-dim);
}

.ccc .ccc-viz-stage {
    display: flex;
    align-items: center;
    justify-content: center;
    justify-content: safe center;   /* see .ccc-plate */
    gap: var(--ccc-s24);
    flex-wrap: wrap;
    background: var(--ccc-m-void);
    border-radius: var(--ccc-r-px);
    padding: var(--ccc-s24);
    overflow-x: auto;
    overflow-y: hidden;
    /* Firefox takes these two; the ::-webkit- rules beside .ccc-strip-scroll
       cover the rest. Without them a stage that scrolls on a narrow screen
       gets the platform's own light scrollbar across a black canvas mount. */
    scrollbar-color: var(--ccc-m-line) var(--ccc-m-void);
    scrollbar-width: auto;
}

/* A caption belonging to the block above it, rather than a heading for the
   block below: same type as .ccc-viz-head, rule on the other edge. */
.ccc .ccc-viz-foot {
    background: var(--ccc-m-void);
    padding: var(--ccc-s16) var(--ccc-s24);
    border-top: 1px solid var(--ccc-m-line);
}

/* Thirty sprite players on one grid: fixed columns and a fixed stage height
   per cell, so the sheets sit on one baseline and the captions form rows
   instead of drifting with each sheet's own dimensions. */
.ccc .ccc-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
    gap: var(--ccc-s32) var(--ccc-s16);
    align-items: start;
    justify-content: stretch;
    width: 100%;
}

.ccc .ccc-gallery-cell {
    display: grid;
    grid-template-rows: 112px auto auto;
    justify-items: center;
    align-items: end;
    gap: var(--ccc-s8);
    min-width: 0;
}

.ccc .ccc-gallery-cell canvas {
    max-width: 100%;
}

.ccc .ccc-gallery-cap {
    margin: 0;
    font-family: var(--ccc-mono);
    font-weight: 500;
    font-size: 0.75rem;
    line-height: 1.5;
    text-align: center;
    color: var(--ccc-m-dim);
    overflow-wrap: anywhere;
}

.ccc .ccc-gallery-stem {
    display: block;
    color: var(--ccc-m-text);
}

/* A sheet drawn on the hero tier rather than the strict fifteen. Marked, not
   hidden: an unexplained 21 under a page about a fifteen-colour budget reads
   as the page contradicting itself. */
.ccc .ccc-gallery-cap .ccc-hero-tier {
    color: var(--ccc-m-gold);
}

.ccc .ccc-viz-controls {
    background: var(--ccc-m-void);
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--ccc-s16) var(--ccc-s24);
    padding: var(--ccc-s16) var(--ccc-s24);
    border-top: 1px solid var(--ccc-m-line);
}

.ccc .ccc-viz-readout {
    /* Fixed measure, tabular figures: a changing number must not reflow
       the row it sits in. */
    min-width: 26ch;
    margin-left: auto;
    font-family: var(--ccc-mono);
    font-weight: 500;
    font-size: 0.875rem;
    line-height: 1.5;
    letter-spacing: 0.04em;
    color: var(--ccc-m-gold);
    font-variant-numeric: tabular-nums;
    text-align: right;
}

/* --------------------------------------------------------------------------
   Controls
   -------------------------------------------------------------------------- */

.ccc .ccc-ctl {
    display: flex;
    flex-direction: column;
    gap: var(--ccc-s8);
    min-width: 180px;
}

/* Button groups inside a control. Laid out rather than left to inter-tag
   whitespace, which collapses to nothing the moment the markup is reformatted
   and leaves eight light-direction buttons welded into one bar. */
.ccc .ccc-ctl [role="group"] {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ccc-s8);
}

/* A sheet stem is a filename, so it keeps its own case. */
.ccc .ccc-btn--stem {
    text-transform: none;
    letter-spacing: 0.04em;
}

.ccc .ccc-ctl > label,
.ccc .ccc-ctl-label {
    font-family: var(--ccc-mono);
    font-weight: 600;
    font-size: 0.875rem;
    line-height: 1.3;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ccc-m-dim);
}

.ccc .ccc-ctl input[type="range"] {
    -webkit-appearance: none;
    appearance: none;
    width: 100%;
    height: 14px;
    margin: 0;
    background: transparent;
    cursor: pointer;
}

.ccc .ccc-ctl input[type="range"]::-webkit-slider-runnable-track {
    height: 4px;
    background: var(--ccc-m-line);
    border: 0;
    border-radius: var(--ccc-r-px);
}

.ccc .ccc-ctl input[type="range"]::-webkit-slider-thumb {
    -webkit-appearance: none;
    appearance: none;
    width: 14px;
    height: 14px;
    margin-top: -5px;
    background: var(--ccc-m-accent);
    border: 0;
    border-radius: var(--ccc-r-px);
    box-shadow: 0 0 0 0 var(--ccc-m-ring);
    transition: box-shadow var(--ccc-motion) var(--ccc-ease),
                background-color var(--ccc-motion) var(--ccc-ease);
}

.ccc .ccc-ctl input[type="range"]::-moz-range-track {
    height: 4px;
    background: var(--ccc-m-line);
    border: 0;
    border-radius: var(--ccc-r-px);
}

.ccc .ccc-ctl input[type="range"]::-moz-range-thumb {
    width: 14px;
    height: 14px;
    background: var(--ccc-m-accent);
    border: 0;
    border-radius: var(--ccc-r-px);
    box-shadow: 0 0 0 0 var(--ccc-m-ring);
    transition: box-shadow var(--ccc-motion) var(--ccc-ease),
                background-color var(--ccc-motion) var(--ccc-ease);
}

.ccc .ccc-ctl input[type="range"]:hover::-webkit-slider-thumb {
    box-shadow: 0 0 0 3px var(--ccc-m-ring);
}

.ccc .ccc-ctl input[type="range"]:hover::-moz-range-thumb {
    box-shadow: 0 0 0 3px var(--ccc-m-ring);
}

.ccc .ccc-ctl input[type="range"]:active::-webkit-slider-thumb {
    background: var(--ccc-m-bright);
    box-shadow: 0 0 0 4px var(--ccc-m-ring);
}

.ccc .ccc-ctl input[type="range"]:active::-moz-range-thumb {
    background: var(--ccc-m-bright);
    box-shadow: 0 0 0 4px var(--ccc-m-ring);
}

.ccc .ccc-ctl input[type="range"]:disabled {
    cursor: not-allowed;
}

.ccc .ccc-ctl input[type="range"]:disabled::-webkit-slider-thumb {
    background: var(--ccc-m-dim);
    box-shadow: none;
}

.ccc .ccc-ctl input[type="range"]:disabled::-moz-range-thumb {
    background: var(--ccc-m-dim);
    box-shadow: none;
}

/* A transform on a pixel-art page reads as blur, so state is carried by
   border, fill and a hard-edged ring, never by movement. */
.ccc .ccc-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--ccc-s8);
    padding: var(--ccc-s12) var(--ccc-s16);
    font-family: var(--ccc-mono);
    font-weight: 600;
    font-size: 0.875rem;
    line-height: 1.2;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ccc-m-text);
    background: var(--ccc-m-panel);
    border: 1px solid var(--ccc-m-line);
    border-radius: var(--ccc-r-ui);
    cursor: pointer;
    transition: color var(--ccc-motion) var(--ccc-ease),
                background-color var(--ccc-motion) var(--ccc-ease),
                border-color var(--ccc-motion) var(--ccc-ease),
                box-shadow var(--ccc-motion) var(--ccc-ease);
}

.ccc .ccc-btn:hover {
    color: var(--ccc-m-bright);
    border-color: var(--ccc-m-accent);
}

.ccc .ccc-btn:active {
    background: var(--ccc-m-line);
}

.ccc .ccc-btn.is-active,
.ccc .ccc-btn[aria-pressed="true"] {
    color: var(--ccc-m-on-accent);
    background: var(--ccc-m-accent);
    border-color: var(--ccc-m-accent);
}

.ccc .ccc-btn.is-active:hover,
.ccc .ccc-btn[aria-pressed="true"]:hover {
    color: var(--ccc-m-on-accent);
    box-shadow: 0 0 0 3px var(--ccc-m-ring);
}

.ccc .ccc-btn:disabled,
.ccc .ccc-btn[aria-disabled="true"] {
    color: var(--ccc-m-dim);
    background: var(--ccc-m-panel);
    border-color: var(--ccc-m-line);
    box-shadow: none;
    cursor: not-allowed;
}

/* --------------------------------------------------------------------------
   Palette swatches
   -------------------------------------------------------------------------- */

.ccc .ccc-swatches {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ccc-s4);
    align-items: flex-start;
}

/* The 66 are grouped into 15 ramp families, which is the section's whole
   claim; without a break between them they read as one undifferentiated
   band and the ramps the copy describes are invisible. */
.ccc .ccc-swatch-family {
    display: flex;
    gap: 1px;
    margin-right: var(--ccc-s12);
}

.ccc .ccc-swatch {
    display: inline-block;
    width: 28px;
    height: 28px;
    padding: 0;
    margin: 0;
    font: inherit;
    background-color: transparent;
    background-clip: padding-box;
    border: 1px solid var(--ccc-m-line);
    border-radius: var(--ccc-r-px);
    cursor: help;
    transition: border-color var(--ccc-motion) var(--ccc-ease);
}

.ccc .ccc-swatch:hover,
.ccc .ccc-swatch:focus-visible {
    border-color: var(--ccc-m-bright);
}

/* A colour the selected sheet does not spend. Dropped to a fifth rather than
   hidden: the shape of the 66 is the point, and a grid that loses two thirds
   of its chips every time you pick a character stops being a master list. */
.ccc .ccc-swatch.is-unused {
    opacity: 0.16;
}

/* The frame-timing strip's playhead. Gold rather than the accent, because the
   accent already means "the cell you selected" one state along, and the two
   have to be distinguishable while both are on screen. */
.ccc .ccc-btn.is-playing {
    box-shadow: inset 0 3px 0 0 var(--ccc-m-gold);
}

.ccc .ccc-btn.is-active.is-playing,
.ccc .ccc-btn[aria-pressed="true"].is-playing {
    box-shadow: inset 0 3px 0 0 var(--ccc-m-gold);
}

/* --------------------------------------------------------------------------
   Equations

   Set in the mono face at body size, centred on their own line, with the
   left-hand term in white and the rest in body ink. Hand-built: nothing on
   this page needs a fraction bar or a summation sign, and a maths typesetter
   would be 280 KB of dependency to render six one-line expressions.
   -------------------------------------------------------------------------- */

/* Wider than the prose measure and narrower than a visualisation. An equation
   is a display element, so it is not bound by the 72-character column, but it
   also has no business running the full 1180px a canvas gets. Higher
   specificity than the `.ccc-section > *` measure rule, which is what makes
   this win without an override. */
.ccc .ccc-hero > .ccc-eq,
.ccc .ccc-section > .ccc-eq {
    max-width: 760px;
}

.ccc .ccc-eq {
    display: block;
    overflow-x: auto;
    margin: var(--ccc-s24) auto;
    padding: var(--ccc-s16) var(--ccc-s24);
    background: var(--ccc-m-panel);
    border-left: 2px solid var(--ccc-m-accent);
    font-family: var(--ccc-mono);
    font-weight: 500;
    font-size: 0.9375rem;
    line-height: 1.9;
    letter-spacing: 0.02em;
    color: var(--ccc-m-text);
    white-space: pre;
    font-variant-numeric: tabular-nums;
}

.ccc .ccc-eq b {
    font-weight: 600;
    color: var(--ccc-m-bright);
}

.ccc .ccc-eq i {
    font-style: normal;
    color: var(--ccc-m-gold);
}

.ccc .ccc-eq u {
    text-decoration: none;
    color: var(--ccc-m-dim);
}

/* A live equation inside a visualisation, where the numbers change as the
   reader drags something. Same type, no rule, tabular so it cannot jitter.
   It takes the visualisation's own width, not the prose measure. */
.ccc .ccc-eq--live {
    max-width: 100%;
    margin: 0;
    padding: var(--ccc-s12) var(--ccc-s24);
    background: var(--ccc-m-void);
    border-left: 0;
    border-top: 1px solid var(--ccc-m-line);
    font-size: 0.875rem;
    line-height: 1.8;
}

/* --------------------------------------------------------------------------
   Draggable maths stages

   A canvas the reader grabs. The cursor is the affordance and the ring is
   the focus state; both are on the canvas itself, since the alternative is
   a caption asking people to try dragging.
   -------------------------------------------------------------------------- */

.ccc .ccc-drag {
    cursor: grab;
    touch-action: none;
    border: 1px solid var(--ccc-m-line);
}

.ccc .ccc-drag:active {
    cursor: grabbing;
}

.ccc .ccc-drag:focus-visible {
    outline: 2px solid var(--ccc-m-accent);
    outline-offset: 2px;
}

/* --------------------------------------------------------------------------
   The tool tour

   Nine tabs, one screenshot at a time. The tab strip is the same button set
   as every other control on the page; the shot sits on the void so the GUI's
   own dark chrome does not float on a second dark card.
   -------------------------------------------------------------------------- */

.ccc .ccc-tour-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: var(--ccc-s8);
    padding: var(--ccc-s16) var(--ccc-s24);
    border-bottom: 1px solid var(--ccc-m-line);
}

.ccc .ccc-tour-shot {
    display: block;
    width: 100%;
    height: auto;
    background: var(--ccc-m-void);
    border: 0;
}

.ccc .ccc-tour-body {
    padding: var(--ccc-s16) var(--ccc-s24);
    border-top: 1px solid var(--ccc-m-line);
}

.ccc .ccc-tour-body p {
    margin: 0;
    max-width: 68ch;
    font-size: 0.9375rem;
    line-height: 1.6;
    color: var(--ccc-m-text);
}

.ccc .ccc-tour-body p + p {
    margin-top: var(--ccc-s8);
    color: var(--ccc-m-dim);
    font-size: 0.875rem;
}

/* --------------------------------------------------------------------------
   The codebase map

   68 files as one bar per file, width proportional to line count, grouped by
   the source project's own directories. Not a treemap: a treemap's areas are
   unreadable below about 40px and half of these files are under 200 lines.
   -------------------------------------------------------------------------- */

.ccc .ccc-map {
    display: flex;
    flex-direction: column;
    gap: var(--ccc-s16);
    padding: var(--ccc-s24);
}

.ccc .ccc-map-area {
    display: flex;
    flex-direction: column;
    gap: var(--ccc-s8);
}

.ccc .ccc-map-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: var(--ccc-s16);
    font-family: var(--ccc-mono);
    font-weight: 600;
    font-size: 0.8125rem;
    line-height: 1.4;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ccc-m-dim);
}

.ccc .ccc-map-head b {
    font-weight: 600;
    color: var(--ccc-m-gold);
    font-variant-numeric: tabular-nums;
}

.ccc .ccc-map-row {
    display: flex;
    gap: 2px;
    height: 14px;
}

.ccc .ccc-map-cell {
    min-width: 2px;
    height: 100%;
    padding: 0;
    /* Tone comes in as a custom property rather than as an inline background,
       so the hover and active rules below still win. An inline `background`
       would outrank both and leave the whole map inert to the pointer. */
    background: var(--cell-tone, var(--ccc-m-line));
    border: 0;
    border-radius: 0;
    cursor: pointer;
    transition: background-color var(--ccc-motion) var(--ccc-ease);
}

.ccc .ccc-map-cell:hover,
.ccc .ccc-map-cell:focus-visible {
    background: var(--ccc-m-accent);
}

.ccc .ccc-map-cell.is-active {
    background: var(--ccc-m-hot);
}

/* --------------------------------------------------------------------------
   Credits and exit
   -------------------------------------------------------------------------- */

.ccc .ccc-credits {
    display: flex;
    flex-direction: column;
    gap: var(--ccc-s16);
    max-width: var(--ccc-measure);
    margin: var(--ccc-s64) auto var(--ccc-s48);
    padding-top: var(--ccc-s32);
    border-top: 1px solid var(--ccc-line);
}

.ccc .ccc-credit-row {
    display: grid;
    grid-template-columns: minmax(0, 24ch) 1fr;
    gap: var(--ccc-s4) var(--ccc-s24);
    align-items: baseline;
}

.ccc .ccc-credit-row > :first-child {
    font-family: var(--ccc-mono);
    font-weight: 600;
    font-size: 0.875rem;
    line-height: 1.4;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ccc-dim);
}

.ccc .ccc-credit-row > :last-child {
    font-family: var(--ccc-font);
    font-weight: 700;
    font-size: 1.125rem;
    line-height: 1.4;
    color: var(--ccc-bright);
}

/* ---------------------------------------------------------------------------
   Source listing (section 12's world.json): a scroll region, not a page of
   code. Lines wrap rather than running off to the right, so the panel scrolls
   in one direction only and a 498-column zone line stays readable; the gutter
   number sits on the baseline of the first visual row of its line, and the
   wrapped remainder aligns under the source column rather than under the
   gutter. Hex string values carry a chip because this file is mostly sky
   colours.
   --------------------------------------------------------------------------- */

.ccc .ccc-code {
    max-height: 30rem;
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    /* The roll assigns scrollTop every frame; smooth scrolling would queue an
       animation against each assignment and stall it. */
    scroll-behavior: auto;
    padding: var(--ccc-s16) 0;
    background: var(--ccc-m-void);
    border: 1px solid var(--ccc-m-line);
    font-family: var(--ccc-mono);
    font-weight: 500;
    font-size: 0.8125rem;
    line-height: 1.75;
    color: var(--ccc-m-text);
    font-variant-numeric: tabular-nums;
}

.ccc .ccc-code-line {
    display: flex;
    align-items: baseline;
}

.ccc .ccc-code-line:hover {
    background: var(--ccc-m-panel);
}

.ccc .ccc-code-num {
    flex: none;
    width: 5ch;
    padding-right: var(--ccc-s16);
    color: var(--ccc-m-line);
    text-align: right;
    user-select: none;
}

.ccc .ccc-code-line:hover .ccc-code-num {
    background: var(--ccc-m-panel);
    color: var(--ccc-m-dim);
}

.ccc .ccc-code-src {
    flex: 1 1 auto;
    min-width: 0;
    padding-right: var(--ccc-s24);
    /* pre-wrap keeps the file's own indentation on the first row of a line;
       break-word is the guard for a token too long to fit a row by itself,
       which is the only way this could still overflow sideways. */
    white-space: pre-wrap;
    overflow-wrap: break-word;
}

.ccc .ccc-code .tok-key { color: var(--ccc-m-bright); }
.ccc .ccc-code .tok-num { color: var(--ccc-m-gold); }
.ccc .ccc-code .tok-lit { color: var(--ccc-m-hot); }
.ccc .ccc-code .tok-pun { color: var(--ccc-m-dim); }

.ccc .ccc-code .tok-chip {
    display: inline-block;
    width: 0.6em;
    height: 0.6em;
    margin-right: 0.35em;
    border: 1px solid var(--ccc-m-line);
}

.ccc .ccc-credit-links {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--ccc-s12);
    margin-left: var(--ccc-s16);
    vertical-align: -3px;
}

.ccc .ccc-credit-links a {
    display: inline-flex;
    color: var(--ccc-dim);
    text-decoration: none;
}

.ccc .ccc-credit-links a:hover {
    color: var(--ccc-accent);
}

.ccc .ccc-credit-links svg {
    display: block;
    width: 18px;
    height: 18px;
}

.ccc .ccc-back {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--ccc-s8);
    width: max-content;
    margin: var(--ccc-s64) auto 0;
    padding: var(--ccc-s12) var(--ccc-s24);
    font-family: var(--ccc-mono);
    font-weight: 600;
    font-size: 0.875rem;
    line-height: 1.2;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--ccc-accent);
    text-decoration: none;
    background: var(--ccc-panel);
    border: 1px solid var(--ccc-line);
    border-radius: var(--ccc-r-ui);
    transition: color var(--ccc-motion) var(--ccc-ease),
                border-color var(--ccc-motion) var(--ccc-ease),
                box-shadow var(--ccc-motion) var(--ccc-ease);
}

.ccc .ccc-back:hover {
    color: var(--ccc-bright);
    border-color: var(--ccc-accent);
    box-shadow: 0 0 0 3px var(--ccc-ring);
}

/* --------------------------------------------------------------------------
   Reduced motion. Canvases are driven by requestAnimationFrame and read
   matchMedia themselves (see the shared helper in ccc26-viz.js); this
   holds the CSS side. Every control state above is carried by colour,
   border or a ring, so the full state range survives at 0ms.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .ccc {
        --ccc-motion: 0ms;
    }

    .ccc *,
    .ccc *::before,
    .ccc *::after {
        transition-duration: 0ms !important;
        animation-duration: 0ms !important;
        animation-iteration-count: 1 !important;
        scroll-behavior: auto !important;
    }
}

/* --------------------------------------------------------------------------
   768px, the site's single breakpoint
   -------------------------------------------------------------------------- */

@media (max-width: 768px) {
    .ccc .ccc-hero {
        padding: calc(var(--ccc-header) + var(--ccc-s32)) 20px var(--ccc-s64);
    }

    .ccc .ccc-section {
        padding: var(--ccc-s64) 20px;
    }

    .ccc .ccc-viz-head,
    .ccc .ccc-viz-controls {
        padding: var(--ccc-s16);
    }

    .ccc .ccc-viz-stage {
        padding: var(--ccc-s16);
    }

    .ccc .ccc-viz-controls {
        flex-direction: column;
        align-items: stretch;
    }

    .ccc .ccc-ctl {
        min-width: 0;
    }

    .ccc .ccc-viz-readout {
        min-width: 0;
        margin-left: 0;
        text-align: left;
    }

    .ccc .ccc-plate {
        padding: var(--ccc-s16);
    }

    /* .ccc-plate--wide returns to the flow. */
    .ccc .ccc-section > .ccc-plate--wide,
    .ccc .ccc-hero > .ccc-trailer,
    .ccc .ccc-hero > .ccc-viz,
    .ccc .ccc-hero > .ccc-strip-scroll,
    .ccc .ccc-section > .ccc-trailer,
    .ccc .ccc-section > .ccc-viz,
    .ccc .ccc-section > .ccc-strip-scroll,
    .ccc .ccc-section > .ccc-fig:has(.ccc-plate--wide),
    .ccc .ccc-section > .ccc-fig:has(.ccc-strip-scroll) {
        max-width: 100%;
    }

    .ccc .ccc-tour-tabs,
    .ccc .ccc-tour-body,
    .ccc .ccc-map {
        padding: var(--ccc-s16);
    }

    .ccc .ccc-eq {
        padding: var(--ccc-s12) var(--ccc-s16);
        font-size: 0.8125rem;
    }

    .ccc .ccc-eq--live {
        padding: var(--ccc-s12) var(--ccc-s16);
    }

    .ccc .ccc-credit-row {
        grid-template-columns: 1fr;
        gap: var(--ccc-s4);
    }

    .ccc .ccc-credit-links {
        display: flex;
        margin-left: 0;
        margin-top: var(--ccc-s8);
    }

    .ccc .ccc-back {
        width: 100%;
    }
}
