/* IRISBOARD browser player.
   One committed look: black glass for the noticeboard, the brand's warm white and orange for the
   pairing card. No light/dark variants — this is a screen on a wall, not a page someone reads. */

/* ── Old TV browsers ──
   TV browsers run engines years old. A property they do not know is dropped silently, so every
   inset, min(), clamp() and place-items below is preceded by the long-hand it replaces — without
   that, a Philips TV gave the stage no size at all and drew the poster in the top-left corner. */

*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%;background:#000;color:#fff;overflow:hidden;
  font-family:'IBM Plex Sans',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;-webkit-font-smoothing:antialiased}
[hidden]{display:none!important}
button{font:inherit}
:focus-visible{outline:3px solid #F26522;outline-offset:3px}

.connecting{position:fixed;top:0;right:0;bottom:0;left:0;inset:0;
  display:flex;align-items:center;justify-content:center;color:#71717a;font-size:15px}

/* ── Pairing ── */
.pair{position:fixed;top:0;right:0;bottom:0;left:0;inset:0;
  display:flex;align-items:center;justify-content:center;padding:24px;background:#F7F4F1;color:#16120F;overflow:auto}
.pair-card{width:100%;max-width:460px;background:#fff;border:1px solid #E8E2DD;border-radius:16px;
  padding:34px 32px 30px;box-shadow:0 18px 50px rgba(22,18,15,.10)}
.pair-logo{display:block;height:46px;width:auto;margin-bottom:26px}
.pair h1{font-size:24px;font-weight:700;letter-spacing:-.02em}
.pair-help{margin-top:8px;color:#4A4340;font-size:15px;line-height:1.55}
.pair-note{margin-top:16px;padding:10px 12px;border-radius:9px;background:#FFF4E5;color:#92400E;font-size:14px}
.pair-label{display:block;margin-top:22px;font-size:12px;font-weight:600;letter-spacing:.06em;
  text-transform:uppercase;color:#7A716C}
.pair-input{display:block;width:100%;margin-top:8px;padding:14px 16px;border:1.5px solid #E8E2DD;border-radius:10px;
  font-family:'IBM Plex Mono',ui-monospace,Consolas,monospace;font-size:24px;font-size:clamp(20px,5vw,26px);
  letter-spacing:.08em;text-align:center;color:#16120F;background:#fff}
.pair-input:focus{border-color:#F26522;outline:none;box-shadow:0 0 0 3px rgba(242,101,34,.18)}
.pair-error{margin-top:10px;color:#B91C1C;font-size:14px}
.pair-button{display:block;width:100%;margin-top:18px;padding:13px 18px;border:0;border-radius:10px;
  background:#F26522;color:#fff;font-size:15px;font-weight:600;cursor:pointer}
.pair-button:hover{background:#C2410C}
.pair-button:disabled{background:#F3B795;cursor:default}

/* ── The noticeboard ── */
.stage{position:fixed;top:0;right:0;bottom:0;left:0;inset:0;width:100%;height:100%;background:#000;overflow:hidden}
.stage.idle{cursor:none}

/* Fit, never crop — a poster is designed to its edges, the same rule the Android player follows.
   z-index 0: the bottom layer. Everything drawn over it sits on a higher one. */
.media{position:absolute;top:0;left:0;width:100%;height:100%;object-fit:contain;background:#000;z-index:0}

/* A video starting up: laid out, so the browser decodes it, but invisible until its first frame is
   ready — the poster before it stays on screen meanwhile (player.js, playVideo). Not [hidden]:
   display:none can stop a TV browser decoding at all. */
.media.starting{opacity:0}

/* The large play button Chromium-based TV browsers draw over a video that has not started. One rule
   each: a browser that does not know one of these pseudo-elements drops the whole rule it is in. */
video.media::-webkit-media-controls{display:none!important}
video.media::-webkit-media-controls-start-playback-button{display:none!important}
video.media::-webkit-media-controls-overlay-play-button{display:none!important}

/* A screen mounted on its side with no rotation set in the operating system: /player?rotate=90 */
/* Sized by player.js from the window rather than 100vh/100vw, which several TV browsers measure
   wrongly once the page is rotated or full screen. The vh/vw values are the first paint only. */
.stage.rotate-90 .media,.stage.rotate-270 .media{width:100vh;height:100vw;top:50%;left:50%}
.stage.rotate-90 .media{-webkit-transform:translate(-50%,-50%) rotate(90deg);transform:translate(-50%,-50%) rotate(90deg)}
.stage.rotate-270 .media{-webkit-transform:translate(-50%,-50%) rotate(-90deg);transform:translate(-50%,-50%) rotate(-90deg)}

.message{position:absolute;top:0;right:0;bottom:0;left:0;inset:0;
  display:flex;align-items:center;justify-content:center;padding:24px;text-align:center;
  color:#A1A1AA;font-size:20px;font-size:clamp(16px,2.2vw,24px)}

.progress{position:absolute;left:50%;top:50%;width:80vw;max-width:560px;
  -webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);text-align:center}
.progress-label{color:#A1A1AA;font-size:16px;font-size:clamp(14px,1.8vw,18px)}
.progress-bar{margin-top:18px;height:6px;border-radius:999px;background:#27272A;overflow:hidden}
.progress-bar span{display:block;height:100%;width:0;background:#FD7B02;transition:width .3s ease}

/* The corner furniture — faint, small, out of the way, as on the Android player.

   Stacked explicitly above the media, and each on a compositing layer of its own (translateZ).
   With neither, the IRISBOARD mark showed over a poster and vanished over a video: TV browsers and
   hardware-decoding Chromium draw a playing video in its own layer, which lands on top of anything
   not placed above it — document order is not enough. */
.caption,.mark,.banner{z-index:2;-webkit-transform:translateZ(0);transform:translateZ(0)}
.caption{position:absolute;top:0;left:0;padding:10px 16px 12px;font-size:12px;color:#fff;opacity:.45;
  text-shadow:0 1px 4px #000;pointer-events:none}
.mark{position:absolute;right:16px;bottom:14px;width:120px;width:clamp(96px,9vw,150px);height:auto;padding:6px 9px;
  border-radius:8px;pointer-events:none;
  /* A dark plate the logo can always be read on. It was a 35% tint at 70% opacity — fine over a
     poster, and close to invisible over a bright video, which is where it was reported missing. */
  background:rgba(0,0,0,.65);opacity:1;box-shadow:0 0 0 1px rgba(255,255,255,.18),0 2px 10px rgba(0,0,0,.45)}
.banner{position:absolute;left:0;right:0;bottom:0;padding:10px 20px;text-align:center;
  font-size:14px;font-size:clamp(13px,1.4vw,16px);color:#000;background:#F5C542}
/* The mark rides above the subscription banner rather than being hidden behind it (player.js sets
   has-banner while one is showing). */
.stage.has-banner .mark{bottom:56px}

/* Everything else drawn over the media, lifted for the same reason. */
.message,.progress{z-index:1}
.start,.unpair{z-index:3;-webkit-transform:translateZ(0);transform:translateZ(0)}
.start{-webkit-transform:translateX(-50%) translateZ(0);transform:translateX(-50%) translateZ(0)}

.start{position:absolute;left:50%;bottom:48px;-webkit-transform:translateX(-50%);transform:translateX(-50%);padding:12px 20px;border:0;border-radius:999px;
  background:rgba(24,24,27,.85);color:#fff;font-size:14px;cursor:pointer;box-shadow:0 8px 30px rgba(0,0,0,.5)}

.unpair{position:absolute;top:0;right:0;bottom:0;left:0;inset:0;
  display:flex;align-items:center;justify-content:center;background:rgba(0,0,0,.6);padding:24px}
.unpair-card{width:100%;max-width:420px;background:#18181B;border:1px solid #27272A;border-radius:14px;padding:24px}
.unpair-card h2{font-size:18px}
.unpair-card p{margin-top:8px;color:#A1A1AA;font-size:14px;line-height:1.5}
.unpair-actions{display:flex;justify-content:flex-end;margin-top:20px}
.unpair-actions button+button{margin-left:10px}   /* not gap: flex gap is newer than these engines */
.unpair-actions button{padding:9px 16px;border-radius:9px;border:1px solid #3F3F46;background:transparent;color:#fff;cursor:pointer}
.unpair-actions .unpair-confirm{background:#DC2626;border-color:#DC2626}

@media (prefers-reduced-motion:reduce){.progress-bar span{transition:none}}

/* The noticeboard cannot be selected or dragged; paired with the player.js rule against the context menu. */
.stage,.stage *{-webkit-user-select:none;-ms-user-select:none;user-select:none}
.stage img,.stage video{-webkit-user-drag:none;user-drag:none}

/* ── A subscription that is switched off or has ended ──
   A large box in the middle of the screen, over the content, with no control on it: nothing here
   can be clicked away, and the media underneath keeps playing — the screen is told, not blanked.
   Above the banner and the mark (z-index 3 and the furniture's 2); below only the unpair dialog,
   which is the administrator's own way out and has to stay reachable. The soft scrim keeps the
   box readable over a bright poster without hiding the content it sits on. */
.blocked{position:absolute;top:0;right:0;bottom:0;left:0;inset:0;z-index:3;
  display:flex;align-items:center;justify-content:center;padding:24px;
  background:rgba(0,0,0,.38);pointer-events:none;
  -webkit-transform:translateZ(0);transform:translateZ(0)}
.blocked-card{width:100%;max-width:760px;max-width:min(78vw,760px);text-align:center;
  padding:40px 44px;padding:clamp(24px,4vw,44px) clamp(24px,5vw,56px);
  border-radius:18px;background:#fff;color:#16120F;border-top:10px solid #DC2626;
  box-shadow:0 24px 80px rgba(0,0,0,.55)}
.blocked-title{font-size:34px;font-size:clamp(24px,4.4vw,48px);font-weight:700;letter-spacing:-.02em;
  line-height:1.1;color:#B91C1C}
.blocked-text{margin-top:16px;font-size:20px;font-size:clamp(16px,2.4vw,28px);line-height:1.45;color:#3F3733}
