/* Family Videos - dark theater on the frankieriviera.com palette.
   Green #48b749 accent, near-black #212529 ground, Montserrat.
   Mobile first; the grid and player scale up from there. */

/* Self-hosted rather than pulled from Google Fonts, so the Content-Security-Policy
   can stay at default-src 'self' with no external origins at all.
   One variable file (wght axis 100-900, verified) covers every weight used here,
   which is 38 KB for the whole typographic range. */
@font-face {
  font-family: 'Montserrat';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('fonts/montserrat.woff2') format('woff2-variations'),
       url('fonts/montserrat.woff2') format('woff2');
}

:root {
  --bg: #212529;
  --surface: #2b3035;
  --surface-2: #343a40;
  --text: #f8f9fa;
  --muted: #adb5bd;
  --sub: #6c757d;
  --accent: #48b749;
  --accent-dark: #38923a;
  --danger: #ff6b6b;
  --border: rgba(248, 249, 250, .10);
  --radius: 10px;
  --shadow: 0 6px 24px rgba(0, 0, 0, .35);
  --font: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  --topbar-h: 56px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  -webkit-text-size-adjust: 100%;
}

body { min-height: 100svh; }

svg { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
svg polygon, svg rect { fill: currentColor; stroke: none; }

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

[hidden] { display: none !important; }

/* ------------------------------------------------------------------ topbar */

.topbar {
  position: sticky; top: 0; z-index: 30;
  display: flex; align-items: center; gap: 12px;
  height: var(--topbar-h);
  padding: 0 14px;
  padding-top: env(safe-area-inset-top);
  height: calc(var(--topbar-h) + env(safe-area-inset-top));
  background: rgba(33, 37, 41, .92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.brand {
  font-weight: 700; font-size: 15px; letter-spacing: -.01em;
  margin-right: auto; cursor: pointer;
}
.brand::after {
  content: ''; display: block; width: 26px; height: 3px;
  background: var(--accent); border-radius: 2px; margin-top: 3px;
}

.back {
  display: inline-flex; align-items: center; gap: 4px;
  background: none; border: 0; color: var(--muted);
  font-family: inherit; font-size: 14px; font-weight: 600;
  cursor: pointer; padding: 8px 6px 8px 0; margin-left: -6px;
}
.back:hover { color: var(--text); }
.back svg { width: 18px; height: 18px; }
.back span { display: none; }

.linkbtn {
  background: none; border: 0; color: var(--muted);
  font-family: inherit; font-size: 14px; font-weight: 600;
  cursor: pointer; padding: 10px 4px;
}
.linkbtn:hover { color: var(--accent); }

/* -------------------------------------------------------------------- misc */

.view { max-width: 1180px; margin: 0 auto; padding: 18px 14px 64px; }

.loading { padding: 60px 20px; text-align: center; color: var(--sub); font-size: 14px; }

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 46px; padding: 0 22px;
  border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--surface-2); color: var(--text);
  font-family: inherit; font-size: 15px; font-weight: 600;
  text-decoration: none; cursor: pointer;
  transition: background .15s, border-color .15s, transform .05s;
}
.btn:hover { background: #3d444b; }
.btn:active { transform: translateY(1px); }

.btn-primary { background: var(--accent); border-color: var(--accent); color: #0c1a0c; }
.btn-primary:hover { background: var(--accent-dark); border-color: var(--accent-dark); }

.btn-ghost { background: transparent; }
.btn-ghost:hover { background: var(--surface-2); }

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

/* ------------------------------------------------------------------- login */

.gate {
  max-width: 380px; margin: 0 auto;
  min-height: 78svh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center;
}
.gate-mark {
  width: 60px; height: 60px; border-radius: 50%;
  border: 2px solid var(--accent);
  display: grid; place-items: center; color: var(--accent);
  margin-bottom: 22px;
}
.gate-mark svg { width: 26px; height: 26px; margin-left: 3px; }
.gate h1 { font-size: 23px; font-weight: 700; margin: 0 0 8px; letter-spacing: -.02em; }
.gate-sub { color: var(--sub); font-size: 14px; margin: 0 0 28px; }
.gate .btn { width: 100%; }

.loginform { width: 100%; margin-top: 14px; display: grid; gap: 12px; }
.loginform input {
  width: 100%; min-height: 46px; padding: 0 14px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--radius);
  font-family: inherit; font-size: 16px; /* 16px stops iOS zooming on focus */
}
.loginform input::placeholder { color: var(--sub); }
.error { color: var(--danger); font-size: 13.5px; margin: 2px 0 0; }

/* ----------------------------------------------------------------- gallery */

.collection { margin-bottom: 34px; }
.collection h2 {
  font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em;
  color: var(--muted); margin: 0 0 14px; display: flex; align-items: center; gap: 10px;
}
.collection h2::after { content: ''; flex: 1; height: 1px; background: var(--border); }

.grid { display: grid; grid-template-columns: 1fr; gap: 16px; }

.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); overflow: hidden;
  cursor: pointer; text-align: left; padding: 0;
  font-family: inherit; color: inherit;
  transition: border-color .15s, transform .12s, box-shadow .15s;
  display: block; width: 100%;
}
.card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: var(--shadow); }

.thumb {
  position: relative; aspect-ratio: 4 / 3; background: #000;
  display: grid; place-items: center; overflow: hidden;
}
.thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.thumb .noimg { color: var(--sub); font-size: 12px; }
.badge {
  position: absolute; right: 8px; bottom: 8px;
  background: rgba(0, 0, 0, .78); color: #fff;
  font-size: 11.5px; font-weight: 600; padding: 3px 7px; border-radius: 5px;
  font-variant-numeric: tabular-nums;
}
.thumb .play {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(0, 0, 0, .18); opacity: 0; transition: opacity .15s;
}
.card:hover .thumb .play { opacity: 1; }
.thumb .play svg { width: 46px; height: 46px; color: #fff; filter: drop-shadow(0 2px 8px rgba(0,0,0,.6)); }

.card-body { padding: 12px 14px 14px; }
.card-body h3 { margin: 0 0 3px; font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
.card-body p { margin: 0; color: var(--sub); font-size: 12.5px; }

/* ------------------------------------------------------------------ player */

.stage { background: #000; margin: -18px -14px 0; }

.videowrap {
  /* How much of the bottom the control bar owns. The tap zones subtract it so they
     never sit over the buttons. It grows on phones, where the time readout wraps
     onto its own line. */
  --ctlh: 64px;
  position: relative; width: 100%; max-width: 1180px; margin: 0 auto;
  aspect-ratio: 4 / 3; background: #000; overflow: hidden;
  -webkit-user-select: none; user-select: none;
}
.videowrap video { width: 100%; height: 100%; display: block; object-fit: contain; background: #000; }

.videowrap.idle .controls { opacity: 0; pointer-events: none; }
.videowrap.idle { cursor: none; }

.bigplay {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgba(0, 0, 0, .3); z-index: 5; cursor: pointer;
  border: 0; padding: 0; font: inherit; color: #fff;
  -webkit-appearance: none; appearance: none;
}
.bigplay svg { width: 64px; height: 64px; color: #fff; filter: drop-shadow(0 3px 12px rgba(0,0,0,.7)); }

/* The paused state uses a small centred badge, NOT the full-bleed scrim above.
   .bigplay is inset:0 at z-index 5 and .tapzone is z-index 4, so showing the
   full-bleed version on every pause would cover both double-tap skip zones and
   disable tap-to-skip for as long as the video stayed paused. The tapzones take
   the outer 32% per side, leaving a 140px free centre on a 390px phone; a 76px
   badge clears them. The full-bleed scrim is kept for the first-run invitation. */
.bigplay-mini {
  inset: auto; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 76px; height: 76px; border-radius: 50%;
  background: rgba(0, 0, 0, .55);
}
.bigplay-mini svg { width: 40px; height: 40px; }
/* While playing, the badge is the pause button, so it comes and goes with the rest
   of the controls rather than being hidden in JS. The full-bleed .bigplay first-run
   invitation deliberately does NOT get this - it stays up until the first play. */
.bigplay-mini { transition: opacity .2s; }
.videowrap.idle .bigplay-mini { opacity: 0; pointer-events: none; }

.spinner {
  position: absolute; top: 50%; left: 50%; width: 42px; height: 42px;
  margin: -21px 0 0 -21px; z-index: 6;
  border: 3px solid rgba(255,255,255,.25); border-top-color: var(--accent);
  border-radius: 50%; animation: spin .8s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

.tapzone {
  position: absolute; top: 0; bottom: var(--ctlh); width: 32%;
  display: grid; place-items: center; z-index: 4;
  opacity: 0; transition: opacity .18s;
}
.tapzone-left  { left: 0; }
.tapzone-right { right: 0; }
/* Fills the band the two side zones leave free, so no part of the picture is dead.
   It sits under .bigplay (z-index 5), which takes its own taps. */
.tapzone-centre { left: 32%; right: 32%; width: auto; }
.tapzone span {
  background: rgba(0,0,0,.62); color: #fff; font-size: 14px; font-weight: 700;
  padding: 12px 16px; border-radius: 999px;
}
.tapzone.flash { opacity: 1; }

/* controls */

.controls {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 10;
  padding: 26px 10px 8px;
  background: linear-gradient(to top, rgba(0,0,0,.88) 0%, rgba(0,0,0,.6) 55%, transparent 100%);
  transition: opacity .2s;
  padding-bottom: calc(8px + env(safe-area-inset-bottom));
}

.scrub { position: relative; height: 26px; display: flex; align-items: center; }
.track {
  position: absolute; left: 0; right: 0; height: 4px; border-radius: 3px;
  background: rgba(255,255,255,.26); overflow: hidden; pointer-events: none;
}
.buffered { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: rgba(255,255,255,.34); }
.played   { position: absolute; left: 0; top: 0; bottom: 0; width: 0; background: var(--accent); }

#seek {
  position: relative; z-index: 2; width: 100%; height: 26px; margin: 0;
  background: transparent; -webkit-appearance: none; appearance: none; cursor: pointer;
}
#seek::-webkit-slider-runnable-track { height: 26px; background: transparent; }
#seek::-moz-range-track { height: 26px; background: transparent; }
#seek::-webkit-slider-thumb {
  -webkit-appearance: none; appearance: none;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--accent); border: 2px solid #fff; margin-top: 6px;
  box-shadow: 0 1px 4px rgba(0,0,0,.6);
}
#seek::-moz-range-thumb {
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--accent); border: 2px solid #fff; box-shadow: 0 1px 4px rgba(0,0,0,.6);
}

.row { display: flex; align-items: center; gap: 2px; padding-top: 2px; }

.ctl {
  position: relative;
  min-width: 44px; height: 44px;   /* 44px touch target */
  display: inline-grid; place-items: center;
  background: none; border: 0; color: #fff; cursor: pointer;
  font-family: inherit; border-radius: 8px;
}
.ctl:hover { background: rgba(255,255,255,.12); }
/* Centred over the icon, not sitting on its lower stroke. At bottom:9px this label
   overlapped the 22px glyph by 8px - 36% of it - which is what made the two skip
   buttons look smudged and half-covered. Centring puts the digits in the arrow's
   hollow, which is the familiar pattern. */
.ctl b {
  /* Inset at the top, not a plain inset:0. The glyph's arrowhead reaches higher
     than its ring, so the SVG's bounding-box centre sits ~1.5px above the ring's
     actual centre; nudging the label box down lands the digits in the hollow. */
  position: absolute; inset: 3px 0 0 0;
  display: grid; place-items: center;
  font-size: 7.5px; font-weight: 700; letter-spacing: 0;
}
.ctl-sm { min-width: 40px; }
.rate { font-size: 13px; font-weight: 700; }

/* The forward-skip icon is the back-skip icon mirrored. This lives here rather than
   as a style="" attribute on the <svg>, because the Content-Security-Policy is
   style-src 'self' with no 'unsafe-inline' - an inline attribute is silently blocked
   and both buttons then render the same direction. Caught by the browser test. */
#fwd30 svg { transform: scaleX(-1); }

/* These two glyphs have to hold a "30" inside them, which the 22px default cannot
   do. The path traces BOTH the r=6 and r=8 arcs, so a 2px stroke fills the gap
   between them into a solid ~4-unit band and leaves a hollow only ~11px across -
   the digits were being swallowed by its left edge. A bigger box plus a thinner
   stroke opens the hollow up. Width/height/stroke only: the mirror transform on
   #fwd30 above must survive. */
#back30 svg, #fwd30 svg { width: 30px; height: 30px; stroke-width: 1.4; }

.time {
  font-size: 12.5px; color: #fff; opacity: .92; padding: 0 8px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
}
.spacer { flex: 1; }

.vol { display: none; width: 78px; accent-color: var(--accent); cursor: pointer; }

.meta { max-width: 1180px; margin: 0 auto; padding: 20px 0 0; }
.meta h1 { font-size: 20px; font-weight: 700; margin: 0 0 4px; letter-spacing: -.02em; }
.meta .sub { color: var(--sub); font-size: 13px; margin: 0 0 18px; }
.actions { display: flex; flex-wrap: wrap; gap: 10px; }
.hint { color: var(--sub); font-size: 12px; margin: 20px 0 0; line-height: 1.7; display: none; }
.hint b { color: var(--muted); font-weight: 600; }

/* contact sheet modal */

.sheetmodal {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(0,0,0,.94);
  display: grid; place-items: center; padding: 16px;
  overflow: auto;
}
.sheetmodal img { max-width: 100%; height: auto; border-radius: 6px; }
.sheetclose {
  position: fixed; top: 12px; right: 16px;
  width: 44px; height: 44px; border-radius: 50%;
  background: rgba(255,255,255,.14); color: #fff; border: 0;
  font-size: 26px; line-height: 1; cursor: pointer;
}

/* ------------------------------------------------------------- breakpoints */

/* The control row is nowrap and nothing in it can shrink: .ctl sets min-width and
   .time sets white-space:nowrap. With an hours-long readout like "1:23:45 / 2:47:14"
   the row needs ~424px, so on a 390px phone .videowrap's overflow:hidden clipped the
   speed and fullscreen buttons clean off. Giving the readout its own line frees the
   ~140px that costs. */
@media (max-width: 559px) {
  .videowrap { --ctlh: 88px; }
  .row  { flex-wrap: wrap; }
  .time { order: -1; flex-basis: 100%; padding: 0 0 2px; }
}

@media (min-width: 560px) {
  .grid { grid-template-columns: repeat(2, 1fr); gap: 18px; }
  .back span { display: inline; }
  .vol { display: inline-block; }
  .view { padding: 22px 20px 72px; }
  .stage { margin: -22px -20px 0; }
}

@media (min-width: 900px) {
  .grid { grid-template-columns: repeat(3, 1fr); }
  .videowrap { aspect-ratio: auto; max-height: calc(100svh - var(--topbar-h) - 190px); height: 62svh; }
  .videowrap video { height: 100%; }
  .meta h1 { font-size: 24px; }
  .hint { display: block; }
}

@media (min-width: 1240px) {
  .grid { grid-template-columns: repeat(4, 1fr); }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

/* ---------------------------------------------------------------- sections */
/*
 * The sections page. Home video is the point of this whole feature, so it gets
 * the accent rail, the poster and the full summary; recorded TV is present only
 * so nothing looks misfiled, and is muted and collapsed to match.
 *
 * Everything here is a class. The Content-Security-Policy is style-src 'self'
 * with no 'unsafe-inline', so a style="" attribute is dropped silently - that is
 * what once made both skip buttons render facing the same way.
 */

.back { text-decoration: none; }
.brandlink { color: inherit; text-decoration: none; }

.collection-head {
  font-size: 13px; font-weight: 700; text-transform: uppercase; letter-spacing: .09em;
  color: var(--muted); margin: 26px 0 8px; display: flex; align-items: center; gap: 10px;
}
.collection-head::after { content: ''; flex: 1; height: 1px; background: var(--border); }

.seg-note { margin: 0 0 14px; color: var(--sub); font-size: 12.5px; }

.seglist { display: grid; grid-template-columns: 1fr; gap: 10px; }

.seg {
  display: grid; grid-template-columns: 116px 1fr; gap: 12px;
  align-items: start; text-align: left; width: 100%;
  background: var(--surface); border: 1px solid var(--border);
  border-left: 3px solid transparent;
  border-radius: var(--radius); padding: 10px; cursor: pointer;
  font-family: inherit; color: inherit;
  transition: border-color .15s, background .15s, transform .12s;
}
.seg:hover { border-color: var(--accent); transform: translateY(-1px); }
.seg-playing { border-color: var(--accent); background: var(--surface-2); }
.seg-playing .seg-body h3 { color: var(--accent); }

.seg-thumb {
  position: relative; aspect-ratio: 4 / 3; background: #000;
  border-radius: 6px; overflow: hidden; display: grid; place-items: center;
}
.seg-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.seg-thumb .noimg { color: var(--sub); font-size: 11px; font-weight: 700; letter-spacing: .08em; }

.seg-body { min-width: 0; padding-top: 2px; }
.seg-body h3 { margin: 0 0 3px; font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
.seg-meta {
  margin: 0 0 5px; color: var(--accent); font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.seg-sum { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.45; }

/* Home video is what this page is for: give it the accent rail. */
.seg-home { border-left-color: var(--accent); }

/* Recorded TV: still legible, deliberately quieter, and smaller so a long run
   of it cannot push the family footage off the screen. */
.seg-tv { border-left-color: transparent; background: transparent; }
.seg-tv .seg-meta { color: var(--sub); font-weight: 500; }
.seg-tv .seg-body h3 { font-size: 14px; font-weight: 500; color: var(--muted); }
.seg-tv .seg-sum { color: var(--sub); font-size: 12.5px; }
.seg-tv .seg-thumb { opacity: .55; }
.seg-tv:hover .seg-thumb { opacity: 1; }

.tvbox { margin-top: 30px; border-top: 1px solid var(--border); padding-top: 14px; }
.tvsummary {
  cursor: pointer; color: var(--muted); font-size: 13px; font-weight: 700;
  text-transform: uppercase; letter-spacing: .09em; padding: 6px 0; list-style: none;
}
.tvsummary::-webkit-details-marker { display: none; }
/* Drawn with borders rather than a glyph. Montserrat has no U+25B8, so a
   character-based marker renders as a missing-glyph box in the self-hosted font. */
.tvsummary::before {
  content: ''; display: inline-block; margin-right: 9px; vertical-align: 1px;
  width: 0; height: 0;
  border-left: 6px solid currentColor;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  transition: transform .15s;
}
.tvbox[open] .tvsummary::before { transform: rotate(90deg); }
.tvsummary:hover { color: var(--text); }
.seglist-tv { margin-top: 8px; }

@media (min-width: 720px) {
  .seg { grid-template-columns: 168px 1fr; gap: 16px; padding: 12px; }
  .seg-body { padding-top: 4px; }
  .back span { display: inline; }
}
