/* ════════════════════════════════════════════════════════════════════════
   THE CODE CARD — a real object that flips.

   Arian: "we need the codes to be an actual card that flips and shows the
   back of it as a music player for the brain entrainment."

   Front  = the collector card art already on the page (the cardPad media).
   Back   = the entrainment player. Two oscillators a few Hz apart, generated
            in the browser. Nothing to download.

   The structure is built by public/js/code-card.js on top of the markup that
   is already there, so with JavaScript off this stylesheet does nothing at
   all and the card stays exactly as it was: front art, working links.

   Built to BRANDING.md, same as codes-next.css:
     • PAINT, DON'T REFRACT (:6470) — the card back and every panel on it is
       a painted directional gradient. backdrop-filter appears exactly twice,
       on the two controls you put your thumb on.
     • NO PURE BLACK, NO PURE WHITE, EXCEPT TEXT (:7414).
     • Buttons are NEVER gradient-filled (:4305) — solid accent, or hairline.
     • One radius (var(--cn-r)) plus the capsule. NO drop shadows, anywhere.
     • Contrast is bought with LIGHT: on a light Code the card falls towards
       warm white, never towards black.
     • Motion is slow. The flip is 900ms on a premium ease.
   Every colour is a --code-* custom property. None is hardcoded.
   ════════════════════════════════════════════════════════════════════════ */

.ccard {
  /* Local fallbacks so the card also works outside .page-code-next. */
  --cc-r: var(--cn-r, 20px);
  --cc-hair: var(--cn-hair, rgba(255, 255, 255, .12));
  --cc-hair-2: var(--cn-hair-2, rgba(255, 255, 255, .22));
  --cc-surface: var(--cn-surface, rgba(255, 255, 255, .05));
  --cc-dim: var(--cn-dim, rgba(255, 255, 255, .55));
  --cc-fade: var(--cn-fade, rgba(255, 255, 255, .28));
  /* The card is LIT, not darkened: the painted face rises off the page at the
     top-left and falls away at the bottom-right. Contrast is bought with
     light, so --cc-lift does the work and --cc-far only closes the gradient.
     Neither end is pure. */
  --cc-lift: #F4F1EA;
  --cc-far: #0A0A0E;
  --cc-flip: 900ms;
  /* THE ONE MARGIN: the card's edge to its picture, all round, and the
     picture to the words under it. */
  --cp-m: 14px;
  --cc-ease: cubic-bezier(.16, .84, .32, 1);
  perspective: 1500px;
}
.is-light .ccard { --cc-lift: #FFFDF8; --cc-far: #6A6A72; }

/* ── The two faces of one object ──────────────────────────────────────── */
.ccard__inner {
  position: relative;
  transform-style: preserve-3d;
  transition: transform var(--cc-flip) var(--cc-ease);
  min-height: 21rem;
}
.ccard.is-flipped .ccard__inner { transform: rotateY(180deg); }
/* FLAT AT REST. The card is a 3D object only while it turns or shows its
   back (code-card.js adds .is-turning before it moves and takes it off once
   the card is back on its face). Lying on its face it is an ordinary
   picture: no layer of its own, no hidden back for the browser to weigh up.
   A picture inside a backface-hidden 3D layer is exactly what browsers
   forget to paint — Arian's iPhone, 2026-09-25: a blank grey card where
   CALM should have been; reproduced in Chromium, where any repaint brought
   the picture back. */
.ccard:not(.is-turning):not(.is-flipped) .ccard__inner { transform-style: flat; }
.ccard:not(.is-turning):not(.is-flipped) .ccard__face--front { transform: none; -webkit-backface-visibility: visible; backface-visibility: visible; }
.ccard:not(.is-turning):not(.is-flipped) .ccard__face--back { visibility: hidden; }

.ccard__face {
  border-radius: var(--cc-r);
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}
.ccard__face--front {
  position: relative; transform: translateZ(.01px);
  /* Only ever seen when a square cardPad leaves room under the art. Painted
     the same way the back is, so the object is lit from one side throughout. */
  background: linear-gradient(158deg,
    color-mix(in srgb, var(--code-bg) 84%, var(--cc-lift)),
    color-mix(in srgb, var(--code-bg) 70%, var(--cc-far)));
}
.ccard__face--back {
  position: absolute; inset: 0;
  transform: rotateY(180deg);
  display: flex; flex-direction: column;
  padding: var(--cp-m);
  gap: 8px;
  overflow: hidden;
  border: 0;
  /* Painted, not refracted. The same 158° diagonal as the hero, but lifted:
     the card has to read as an object sitting ON the page, and the only
     honest way to do that without a shadow is to light it. */
  background:
    radial-gradient(128% 84% at 84% 2%, color-mix(in srgb, var(--code-accent) 26%, transparent), transparent 62%),
    linear-gradient(158deg,
      color-mix(in srgb, var(--code-bg) 84%, var(--cc-lift)) 0%,
      color-mix(in srgb, var(--code-bg) 95%, var(--cc-lift)) 38%,
      var(--code-bg) 66%,
      color-mix(in srgb, var(--code-bg) 70%, var(--cc-far)) 100%);
  color: var(--code-ink, #fff);
}
/* The face that is turned away must never be reachable — not by a tab key,
   not by a screen reader, not by a stray click through the card. */
.ccard__face[inert],
.ccard__face[aria-hidden="true"] { pointer-events: none; }

/* ── The flip ─────────────────────────────────────────────────────────────
   Nothing is laid over the art. Arian, 2026-09-24: "Remove all of the
   'entrainment' coverups. We will provide all of the correct code cards."
   The card itself turns over: tap it, or reach it with the keyboard and
   press Enter or Space (a card with an ACTIVATE bar turns from the bar). */
.ccard__face--front { cursor: pointer; }
.ccard__face--front:focus-visible { outline: 1px solid var(--code-accent, currentColor); outline-offset: 4px; }

/* ── The back: head ───────────────────────────────────────────────────── */
.ccard__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--s-2); }
.ccard__eyebrow {
  font-size: var(--fs-micro, .58rem); letter-spacing: var(--track-hud, .3em);
  text-transform: uppercase; color: var(--cc-fade); margin: 0;
}
.ccard__num {
  font-family: var(--font-mark, inherit); font-size: 1.05rem; line-height: 1; margin: 0;
  background: linear-gradient(135deg, var(--code-grad-from), var(--code-grad-to));
  -webkit-background-clip: text; background-clip: text; color: transparent;
}

/* ── The back: the Code's own picture ──────────────────────────────────
   Arian, 2026-10-04: "artworks not even working right and just a weird
   shape", and then "Don't ever try to crop them. They're perfectly made for
   a reason and 9 x 16 and 4 x 5". The back shows the Code's art
   (src/views/code-player.js, playerArt) WHOLE, at its own shape: as large as
   the room the readings leave allows, centred in it, its own corners
   rounded, lifted off the face as the buttons are. Never cut to fill the
   room. Nothing is laid over it. */
.ccard__viz { position: relative; flex: 1 1 auto; min-height: 4.5rem; margin-bottom: calc(var(--cp-m) - 8px); }
/* Every other row keeps its height; the picture is the one that gives. */
.ccard__face--back > :not(.ccard__viz) { flex: none; }
.ccard__art {
  position: absolute; inset: 0; margin: auto;
  width: auto; height: auto; max-width: 100%; max-height: 100%;
  border-radius: calc(var(--cc-r) * .7);
  box-shadow: -3px -3px 7px color-mix(in srgb, var(--code-bg), #fff 9%), 3px 3px 7px color-mix(in srgb, var(--code-bg), #000 45%);
}

/* ── The back: the Academy's player (Arian, 2026-10-01: "when you get to
   the media player … it needs to look like how the media player looks like
   in academy"; lesson-player.css). Plain thin readouts; the place as a groove
   pressed into the face, filled in the Code's colour; back, play and stop as
   round soft buttons, play the one that goes on, in the Code's flat colour. */
.ccard__rows { display: flex; gap: var(--s-4); }
.ccard__rows div { display: grid; gap: var(--s-1); }
.ccard__k {
  font-size: var(--fs-micro, .58rem); letter-spacing: var(--track-hud, .3em);
  text-transform: uppercase; color: var(--cc-fade);
}
.ccard__v { font-family: var(--font-ui, inherit); font-weight: 300; font-size: .95rem; letter-spacing: .04em; color: var(--code-ink, #fff); }

.ccard__bar {
  position: relative; height: 8px; border-radius: var(--r-pill, 999px); overflow: hidden;
  background: color-mix(in srgb, var(--code-bg) 88%, #000);
  box-shadow: inset 2px 2px 4px color-mix(in srgb, var(--code-bg), #000 45%), inset -1px -1px 3px color-mix(in srgb, var(--code-bg), #fff 10%);
}
.ccard__bar i {
  position: absolute; inset: 0 auto 0 0; display: block; border-radius: inherit;
  width: var(--p, 0%);
  background: linear-gradient(90deg, var(--code-ramp-a, var(--code-accent)), var(--code-ramp-b, var(--code-accent)));
  transition: width 260ms linear;
}
.ccard__time {
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--font-ui, inherit); font-weight: 300; font-size: .72rem; letter-spacing: .1em;
  color: var(--cc-dim); font-variant-numeric: tabular-nums;
}
.ccard__time b { font-weight: inherit; color: var(--code-ink, #fff); }

/* IN PROPORTION TO THE CARD (Arian, 2026-10-04: "some buttons feel too big
   for the card they're on"): back and stop at the 44 px a finger needs, play
   a step larger, and no bigger. */
.ccard__controls { display: flex; align-items: center; justify-content: center; gap: 1.1rem; }
.ccard__back, .ccard__stop {
  flex: none; display: grid; place-items: center; width: 44px; height: 44px; padding: 0;
  border: 0; border-radius: 50%; cursor: pointer; font: inherit;
  background: var(--code-bg); color: var(--code-ink, #fff);
  box-shadow: -3px -3px 7px color-mix(in srgb, var(--code-bg), #fff 9%), 3px 3px 7px color-mix(in srgb, var(--code-bg), #000 50%);
}
.ccard__back:active, .ccard__stop:active { box-shadow: inset 2px 2px 5px color-mix(in srgb, var(--code-bg), #000 50%), inset -2px -2px 5px color-mix(in srgb, var(--code-bg), #fff 9%); }
.ccard__back svg { width: 15px; height: 15px; fill: none; stroke: currentColor; stroke-width: 1.6; }
.ccard__stop svg { width: 13px; height: 13px; fill: currentColor; }
.ccard__play {
  flex: none; display: grid; place-items: center; width: 56px; height: 56px; padding: 0;
  border: 0; border-radius: 50%; cursor: pointer;
  /* The card's own ground lifted, as BACK and STOP beside it: every button is the soft capsule (Arian, 2026-10-03: "Everywhere"; components.css). */
  background: var(--code-bg); color: var(--code-ink, #fff);
  box-shadow: -4px -4px 9px color-mix(in srgb, var(--code-bg), #fff 9%), 4px 4px 9px color-mix(in srgb, var(--code-bg), #000 50%);
}
.ccard__play:active { box-shadow: inset 2px 2px 5px color-mix(in srgb, var(--code-bg), #000 50%), inset -2px -2px 5px color-mix(in srgb, var(--code-bg), #fff 9%); }
.ccard__play svg { grid-area: 1 / 1; width: 24px; height: 24px; fill: currentColor; }
.ccard__i-pause, .ccard.is-playing .ccard__i-play { display: none; }
.ccard.is-playing .ccard__i-pause { display: block; }
.ccard__play[disabled] { opacity: .45; cursor: default; }

.ccard__note {
  margin: 0; display: flex; align-items: center; justify-content: center; gap: .6em;
  font-size: var(--fs-micro, .58rem); letter-spacing: var(--track-hud, .3em);
  text-transform: uppercase; color: var(--cc-fade);
}
/* Headphones said as the icon, as everywhere an icon fits (BRAND-RULES §1). */
.ccard__note .icon { flex: none; }

/* Focus is never removed, only drawn in the Code's own light. */
.ccard :focus-visible,
.ccard__face--back:focus-visible { outline: 2px solid var(--code-accent); outline-offset: 3px; }

/* A short card (a square or landscape cardPad instead of a 9:16 one) drops
   the quietest line before it ever squeezes the player. The picture takes
   the slack, because it is the only row that can give any. */
.ccard.is-short .ccard__note { display: none; }
.ccard.is-short .ccard__viz { min-height: 4.5rem; }

/* ── THE SESSION'S CARD (/codes/:slug/enter): the same back, standing on its
   own, already turned. Its picture is as large as the screen allows with the
   player under it, on one screen between the top bar and the dock, and the
   card is the picture's width and the one margin round it, so the margin is
   the same on every side, whatever the picture's shape (9:16, 4:5). ───── */
.ccard--solo {
  --cp-m: 16px;
  /* Everything on that first screen that is not the picture: the bar, the
     line over the card, the card's words and controls, the dock. A small
     phone keeps a picture worth seeing (15rem tall) and scrolls a little. */
  --cp-chrome: calc(var(--nav-h) + var(--dock-room, 0px) + 24rem);
  --art-w: min(25rem, 100vw - 2 * var(--gutter) - 2 * var(--cp-m), max(100svh - var(--cp-chrome), 15rem) * var(--art-r, .5625));
  /* No narrower than back · play · stop need. */
  width: max(13.5rem, var(--art-w) + 2 * var(--cp-m)); max-width: 100%;
  margin-inline: auto; perspective: none;
  padding-block: var(--deck-pt, 1.2rem) var(--deck-pb, 1.6rem);
}
.ccard.ccard--solo .ccard__face.ccard__face--back {
  position: relative; inset: auto; transform: none; visibility: visible;
  -webkit-backface-visibility: visible; backface-visibility: visible;
}
.ccard--solo .ccard__viz { flex: none; min-height: 0; }
.ccard--solo .ccard__art { position: static; display: block; width: min(100%, var(--art-w)); height: auto; max-width: none; max-height: none; margin: 0 auto; }
@media (min-width: 860px) {
  .cn-hero__inner > .ccard--solo { grid-column: 1; grid-row: 1 / span 2; }
  .page-sequence .cn-hero__inner { grid-template-columns: auto minmax(0, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  .ccard__inner { transition-duration: 1ms; }
  .ccard__bar i { transition: none; }
}
