/* ==========================================================================
   KurzKeySite — Design tokens
   Concept: front panel of a Kurzweil keyboard. Dark chassis, a real status
   display (mode line, category bar, main line, soft-key labels) as the
   signature element, wired to unlabelled physical buttons below it via thin
   fan-out connector lines — modeled directly on the hardware.
   ========================================================================== */

:root{
  --chassis:        #17171a;
  --chassis-raised: #1e1f22;
  --chassis-recess: #101012;
  --hairline:       #36373c;
  --hairline-soft:  #2a2b2f;

  --text-main:      #ece9e2;
  --text-dim:       #9a9a9e;
  --text-faint:     #66666c;

  --lcd:            #5be3cc;
  --lcd-dim:        #2f5a53;
  --lcd-glow:       rgba(91,227,204,0.35);

  --screen-blue:    #1f8fff;
  --screen-amber:   #f0c76a;

  --amber:          #f2a65a;

  --led-on:         #5fd97a;
  --led-on-glow:    rgba(95,217,122,0.55);
  --led-wait:       #f2a65a;
  --led-wait-glow:  rgba(242,166,90,0.5);

  /* Artwork inside the display comes from the per-category rules further
     down (--art-top / --art-main, cut out of the Forte screenshots).
     To fall back to the CSS-drawn piano keys everywhere, uncomment:
       --art-override: none;
     Every .kw-art layer honours it. */
  /* --art-override: none; */

  --radius-panel:   14px;
  --radius-btn:     6px;

  --font-display:   'JetBrains Mono', 'Courier New', monospace;
  --font-body:      'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;

  --maxw: 1040px;
}

@media (prefers-reduced-motion: reduce){
  *{ animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
}

*{ box-sizing: border-box; }
html{ scroll-behavior: smooth; }

body{
  margin: 0;
  background: var(--chassis);
  background-image:
    radial-gradient(circle at 15% 0%, rgba(255,255,255,0.025), transparent 40%),
    radial-gradient(circle at 85% 100%, rgba(31,143,255,0.04), transparent 45%);
  color: var(--text-main);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
a{ color: inherit; }
.wrap{ max-width: var(--maxw); margin: 0 auto; padding: 0 28px; }

.rack-rail{
  height: 10px;
  background: repeating-linear-gradient(90deg, var(--hairline) 0 2px, transparent 2px 14px);
  opacity: 0.5;
}

/* ---------- Header: nothing but the name ---------- */
header{
  position: sticky; top: 0; z-index: 50;
  background: rgba(23,23,26,0.86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--hairline);
}
.header-inner{
  display: flex; align-items: center; justify-content: center;
  padding: 18px 28px; max-width: var(--maxw); margin: 0 auto;
}
.brand{
  font-family: var(--font-display); font-weight: 700;
  font-size: clamp(18px, 3.4vw, 34px);
  letter-spacing: clamp(0.10em, 0.9vw, 0.22em);
  text-decoration: none; color: #fff;
  /* letter-spacing adds trailing space after the last glyph — pull it back */
  margin-right: -0.2em;
}

/* ---------- Hero: the display panel, nothing else ---------- */
.hero{ padding: 40px 0 44px; }

.kw-panel{ max-width: 760px; margin: 0 auto; container-type: inline-size; }

.kw-bezel{
  background: linear-gradient(180deg, #2c2d31, #202124);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-panel);
  padding: 22px 22px 8px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.04), 0 16px 34px rgba(0,0,0,0.45);
}

/* -- the screen itself -- */
.kw-screen{
  border-radius: 3px;
  overflow: hidden;
  font-family: var(--font-body);
  background: #04070f;
}

/* Mode line: always visible, black bar, white text */
.kw-screen-top{
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  background: #000;
  padding: 7px 12px;
  font-family: var(--font-body);
}
.kw-mode{ font-size: clamp(11px, 2.2cqw, 16px); font-weight: 600; color: #fff; white-space: nowrap; }
.kw-tagline{
  font-family: var(--font-display); font-size: clamp(8px, 1.6cqw, 11px); letter-spacing: 0.04em;
  color: var(--text-dim); text-align: right;
}

/* Per-category theming. Each news item's category sets the accent colour and
   the two pieces of artwork; everything else in the display reads --cat.
   The colours are the PC4's own category colours, lifted in value until they
   clear 4.5:1 against the black they sit on. */
.kw-screen[data-cat="apps"]  { --cat:#1f70ff; --art-top:url('assets/art/apps-top.png');   --art-main:url('assets/art/apps-main.png'); }
.kw-screen[data-cat="sheets"]{ --cat:#ff770c; --art-top:url('assets/art/sheets-top.png'); --art-main:url('assets/art/sheets-main.png'); }
.kw-screen[data-cat="guides"]{ --cat:#914dff; --art-top:url('assets/art/guides-top.png'); --art-main:url('assets/art/guides-main.png'); }
.kw-screen[data-cat="sounds"]{ --cat:#ff2b2b; --art-top:url('assets/art/sounds-top.png'); --art-main:url('assets/art/sounds-main.png'); }
.kw-screen[data-cat="links"] { --cat:#dfff3d; --art-top:url('assets/art/links-top.png');  --art-main:url('assets/art/links-main.png'); }
.kw-screen[data-cat="info"]  { --cat:#3de2ff; --art-top:url('assets/art/info-top.png');   --art-main:url('assets/art/info-main.png'); }

/* Artwork bands. The image layer sits on top of the CSS-drawn piano keys, so
   a missing file degrades to the drawn variant instead of a blank box; setting
   --art-override to `none` in :root switches every band to the drawn one.
   Both bands carry the category-coloured rules the hardware draws. */
.kw-art{
  position: relative;
  background-color: #04070f;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;
  border-top: 1px solid var(--cat);
  border-bottom: 1px solid var(--cat);
}
.kw-art-top{
  height: clamp(20px, 7.5cqw, 56px);
  /* the rule along the bottom is drawn by .kw-cat-rule, which starts where
     the tab ends — tab and title band read as one piece that way */
  border-bottom: none;
  background-image:
    var(--art-override, var(--art-top)),
    repeating-linear-gradient(97deg, #0c3372 0 24px, #05193d 24px 30px);
}
.kw-art-main{
  /* the short-info box sits at the top of this band; the padding below it is
     the stretch of artwork left uncovered */
  padding-bottom: clamp(34px, 12.5cqw, 90px);
  background-image:
    var(--art-override, var(--art-main)),
    repeating-linear-gradient(97deg, transparent 0 15px, rgba(0,0,0,0.6) 15px 27px, transparent 27px 42px),
    repeating-linear-gradient(97deg, #1a67ca 0 40px, #0b3f86 40px 42px);
}

/* Category tab — sits on the lower edge of the upper artwork band like the tab
   of a file folder: black, with the category name in the category colour. The
   rule beside it picks up where the tab ends and runs to the right edge. */
.kw-cat-row{
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: flex-end;
}
.kw-cat-rule{
  flex: 1;
  height: 1px;
  background: var(--cat);
}
.kw-cat{
  flex: 0 1 auto;
  display: block; max-width: 60%;
  font-family: var(--font-body); font-weight: 700;
  font-size: clamp(9px, 1.9cqw, 14px); line-height: 1.25;
  color: var(--cat);
  background: #000;
  padding: clamp(2px, 0.5cqw, 4px) clamp(14px, 3cqw, 22px) clamp(2px, 0.5cqw, 4px) clamp(8px, 1.6cqw, 12px);
  white-space: nowrap; overflow: hidden;
  /* slanted trailing edge, the way the PC4 draws it */
  clip-path: polygon(0 0, calc(100% - 9px) 0, 100% 100%, 0 100%);
}

/* News: the black title band, then the artwork carrying the short info */
.kw-news, .kw-art{ transition: opacity 0.16s ease; }
.kw-screen.is-swapping .kw-news,
.kw-screen.is-swapping .kw-art{ opacity: 0.15; }

.kw-main{
  display: flex; align-items: center; gap: clamp(8px, 3cqw, 24px);
  padding: clamp(9px, 2.6cqw, 19px) clamp(8px, 2.2cqw, 16px);
  background: #000;
}
.kw-num, .kw-name{
  font-family: var(--font-body); font-weight: 700;
  color: #fff;
  /* room for descenders — the title is clipped horizontally, so the line box
     has to be taller than the ink or the g/j/y tails get cut off too */
  line-height: 1.35;
}
.kw-num{ font-size: clamp(20px, 5.8cqw, 44px); font-variant-numeric: tabular-nums; }
.kw-name{
  font-size: clamp(20px, 6.1cqw, 46px);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.kw-flag{
  margin-left: auto;
  align-self: flex-end;
  font-family: var(--font-display); font-size: clamp(8px, 1.5cqw, 11px); font-weight: 700;
  letter-spacing: 0.12em; color: #fff; white-space: nowrap;
  border: 2px solid #fff; border-radius: 3px;
  padding: 1px 5px;
}

/* Short info: a translucent box laid over the artwork, dark enough for white
   text on the brightest photo and light enough to read the picture through.
   The minimum height holds the display steady while paging — it takes a short
   info of about three lines, which is what the entries are written to. */
.kw-desc{
  position: relative;
  margin: 0;
  padding: clamp(7px, 1.8cqw, 13px) clamp(8px, 2.2cqw, 16px);
  min-height: clamp(40px, 13cqw, 94px);
  background: rgba(0, 0, 0, 0.72);
  color: #fff; font-size: clamp(10px, 2.1cqw, 15px); line-height: 1.5;
}

/* Paging arrows, centred on the artwork left uncovered below the info box.
   JS unhides them; without JS the display shows the first item and stays. */
.kw-nav{
  position: absolute;
  bottom: clamp(6px, 4.1cqw, 29px);
  width: clamp(22px, 4.6cqw, 34px); height: clamp(22px, 4.6cqw, 34px);
  display: grid; place-items: center;
  padding: 0; cursor: pointer;
  border: 1px solid rgba(255,255,255,0.35); border-radius: 50%;
  background: rgba(0,0,0,0.45);
  color: #fff;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.kw-nav svg{ width: 58%; height: 58%; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.kw-nav.prev{ left: clamp(6px, 1.4cqw, 12px); }
.kw-nav.next{ right: clamp(6px, 1.4cqw, 12px); }
.kw-nav:hover{ background: rgba(0,0,0,0.75); border-color: var(--cat); color: var(--cat); }
.kw-nav[hidden]{ display: none; }

/* Soft keys: white labels on black, thin rules between them, the label of the
   category currently on screen picked out in that category's colour. */
.kw-softkeys{
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr));
  background: #000;
}
.kw-softkeys .sk{
  text-align: center;
  font-family: var(--font-body); font-weight: 700;
  font-size: clamp(7px, 1.9cqw, 15px); letter-spacing: 0.02em;
  padding: 7px 1px;
  overflow: hidden;
  color: #fff;
  border-right: 1px solid rgba(255,255,255,0.22);
  transition: color 0.15s ease;
}
.kw-softkeys .sk:last-child{ border-right: none; }
.kw-softkeys .sk.current{ color: var(--cat); }

/* -- connectors + physical buttons -- */
.kw-connectors{ display: block; width: 100%; height: 34px; }
.kw-connectors line{ stroke: #8b8c90; stroke-width: 1.4; }

.kw-buttons{
  display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: clamp(5px, 1.9cqw, 14px);
  padding: 0 0 18px;
}
.kw-btn{
  display: block; height: clamp(26px, 6cqw, 46px); padding: 0;
  border: 1px solid #9b9ca0;
  border-radius: 3px;
  background: linear-gradient(180deg, #d6d7d9, #bcbdc0);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.6), 0 2px 4px rgba(0,0,0,0.45);
  transition: background 0.15s ease, box-shadow 0.15s ease, transform 0.08s ease;
}
a.kw-btn:hover{
  background: linear-gradient(180deg, #ffffff, #cfd0d3);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.8), 0 0 12px rgba(31,143,255,0.5);
}
a.kw-btn:active{ transform: translateY(1px); }
button.kw-btn[disabled]{
  cursor: default;
  background: linear-gradient(180deg, #a9aaad, #909195);
  opacity: 0.75;
}

/* ---------- Section scaffolding ---------- */
section{ padding: 48px 0; scroll-margin-top: 88px; }
.section-head{
  display: flex; align-items: baseline; justify-content: space-between; gap: 24px;
  margin-bottom: 24px; border-bottom: 1px solid var(--hairline); padding-bottom: 14px;
}
.section-head h2{
  font-family: var(--font-display); font-size: 20px; margin: 0; letter-spacing: -0.01em;
}

/* ---------- Module grid ---------- */
.rack{
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 16px;
}
.module{
  background: linear-gradient(180deg, var(--chassis-raised), var(--chassis));
  border: 1px solid var(--hairline);
  border-radius: var(--radius-panel);
  padding: 20px;
  display: flex; flex-direction: column; gap: 12px;
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.module:hover{ border-color: var(--hairline-soft); transform: translateY(-2px); }
.module-top{ display: flex; align-items: center; justify-content: space-between; }
.module-num{ font-family: var(--font-display); font-size: 11px; color: var(--text-faint); letter-spacing: 0.1em; }
.status{
  display: flex; align-items: center; gap: 6px;
  font-family: var(--font-display); font-size: 10px; letter-spacing: 0.08em; text-transform: uppercase;
}
.status .dot{ width: 6px; height: 6px; border-radius: 50%; }
.status.live .dot{ background: var(--led-on); box-shadow: 0 0 6px var(--led-on-glow); }
.status.live{ color: var(--led-on); }
.status.wait .dot{ background: var(--led-wait); box-shadow: 0 0 6px var(--led-wait-glow); }
.status.wait{ color: var(--led-wait); }

.module-icon{ width: 32px; height: 32px; color: var(--text-dim); }
.module h3{ margin: 0; font-size: 17px; font-family: var(--font-body); font-weight: 600; }
.module p{ margin: 0; color: var(--text-dim); font-size: 14px; flex-grow: 1; }
.module-foot{
  display: flex; align-items: center; justify-content: space-between;
  padding-top: 8px; border-top: 1px solid var(--hairline-soft);
}
.module-link{ font-family: var(--font-display); font-size: 12px; text-decoration: none; color: var(--lcd); }
.module-link:hover{ text-decoration: underline; }
.module-link.disabled{ color: var(--text-faint); pointer-events: none; }
/* A second link in the foot: muted, so the first one stays the obvious one to
   press. Two links in the accent colour would read as a choice between equals,
   and opening the app is what the tile is for. */
.module-link.second{ color: var(--text-dim); }
.module-link.second:hover{ color: var(--lcd); }
.access-tag{ font-size: 11px; color: var(--text-faint); font-family: var(--font-display); }

/* Placeholder tiles: no title, no description — just a note */
.module-empty{ justify-content: space-between; }
.module-empty:hover{ transform: none; }
.module-empty .soon{
  font-family: var(--font-display); font-size: 12px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--text-faint);
  display: flex; align-items: center; justify-content: center;
  min-height: 96px; margin: 0;
  border: 1px dashed var(--hairline-soft); border-radius: 8px;
}

/* ---------- Screenshot tile ---------- */
/* A tile whose front is a screenshot and whose back is the usual tile text.
   Two states on purpose:
     no JavaScript - the two faces sit above each other, image first, and
       everything is readable and clickable as on any other tile;
     .flip-ready   - script.js stacks them and a click turns the card over.
   Written that way round so the tile is never a dead image with no link. */
.module-shot .shot-faces{ display: flex; flex-direction: column; gap: 12px; flex-grow: 1; }
.module-shot .shot-back{ display: flex; flex-direction: column; gap: 12px; flex-grow: 1; }
.shot-img{
  display: block; width: 100%; height: auto;
  border: 1px solid var(--hairline-soft); border-radius: 8px;
}
/* The h3 on the back already carries the name while both faces are visible. */
.module-shot:not(.flip-ready) .shot-cap{ display: none; }

.sr-only{
  position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ---- flipping, once script.js is there ---- */
.module-shot.flip-ready{
  position: relative;
  padding: 0;
  /* Measured, not guessed: the back holds the same text as any other tile, and
     in the narrowest column the rack allows (220px) it needs 340px of it. */
  min-height: 352px;
  perspective: 1100px;
}
/* The card itself must not move: the lift would fight the rotation, and the
   image already answers the pointer. */
.module-shot.flip-ready:hover{ transform: none; }

.flip-ready .shot-faces{
  position: absolute; inset: 0;
  display: block;
  transform-style: preserve-3d;
  transition: transform 0.62s cubic-bezier(0.22, 0.68, 0.24, 1);
}
.module-shot.is-flipped .shot-faces{ transform: rotateY(180deg); }

.flip-ready .shot-face{
  position: absolute; inset: 0;
  border-radius: var(--radius-panel);
  overflow: hidden;
  backface-visibility: hidden;
}
.flip-ready .shot-front{ background: var(--chassis-recess); }
.flip-ready .shot-back{
  transform: rotateY(180deg);
  padding: 20px;
  background: linear-gradient(180deg, var(--chassis-raised), var(--chassis));
}

.flip-ready .shot-img{
  width: 100%; height: 100%;
  object-fit: cover; object-position: left top;
  border: 0; border-radius: 0;
  transition: transform 0.4s ease, filter 0.4s ease;
  filter: saturate(0.92) brightness(0.86);
}
.flip-ready .shot-front:hover .shot-img,
.flip-ready .shot-front:focus-within .shot-img{ transform: scale(1.03); filter: none; }

.flip-ready .shot-cap{
  position: absolute; left: 0; right: 0; bottom: 0;
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 56px 16px 15px;
  /* The screenshot under the caption is a toolbar full of small controls, so
     the scrim has to be nearly opaque where the words are - a light veil left
     the title fighting with the buttons behind it. */
  background: linear-gradient(180deg, rgba(14,14,16,0) 0%, rgba(14,14,16,0.72) 42%, rgba(14,14,16,0.96) 72%);
  pointer-events: none;
}
.shot-title{ font-family: var(--font-body); font-weight: 600; font-size: 17px; color: var(--text-main); }
.shot-hint{
  font-family: var(--font-display); font-size: 11px; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--lcd);
}

/* The whole front is the button, so the target is the tile, not a word in it. */
.shot-open{
  position: absolute; inset: 0;
  border: 0; background: none; padding: 0;
  cursor: pointer;
}
.shot-open:focus-visible{ outline-offset: -4px; }

/* Small and in the top row, not in the foot: the foot carries the link and the
   file type, and those say more than a second way back - the whole back face
   turns over on a tap anyway, and Esc does it from the keyboard. */
.shot-close{
  display: flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; margin: -6px -6px -6px 0;
  border: 0; background: none; padding: 0; cursor: pointer;
  color: var(--text-faint);
}
.shot-close svg{ width: 17px; height: 17px; }
.shot-close:hover{ color: var(--lcd); }
.flip-ready .shot-back .module-top{ gap: 10px; }
.flip-ready .shot-back .status{ margin-left: auto; }

/* ---------- Info / footer ---------- */
.about{ border-top: 1px solid var(--hairline); }
.about p{ color: var(--text-dim); max-width: 68ch; }

footer{ border-top: 1px solid var(--hairline); padding: 28px 0 44px; }
.footer-inner{
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 24px; flex-wrap: wrap;
}
.disclaimer{ font-size: 12.5px; color: var(--text-faint); max-width: 60ch; line-height: 1.6; }
.footer-brand{ font-family: var(--font-display); font-size: 12px; color: var(--text-faint); }

:focus-visible{ outline: 2px solid var(--screen-blue); outline-offset: 2px; }

/* ---------- Narrow screens ---------- */
@media (max-width: 620px){
  /* The display itself scales through container units; only the chassis
     padding and the tagline need a hand on small screens. */
  .kw-bezel{ padding: 14px 14px 6px; }
  .kw-tagline{ display: none; }
}
