/* ============================================================
   LINKS — page layer

   Ported from the approved mockup (redesign/mockups/links.html) and then put on
   the system scale: every value below is a token, so this page cannot drift
   away from the rest of the site the way the last build did.

   Two mockup-only blocks are gone and nothing else changed: the skin switcher
   with its fake account chrome, and the player-shape switcher. Both existed so
   the design could be reviewed standalone; the real page gets its navbar from
   site.js and its player shape from the link itself.
   ============================================================ */

/* ---------- page head ---------- */
.lk-page { padding-bottom:var(--s-11); }
/* .pg-head / .pg-title / .pg-sub now live in system.css - three pages use them. */

/* ---------- toolbar ---------- */
.lk-bar { display:flex; gap:var(--s-4); flex-wrap:wrap; align-items:stretch; margin:var(--s-8) 0 var(--s-4); }

.lk-search { position:relative; flex:1; min-width:240px; display:flex; align-items:center; }
.lk-search svg { position:absolute; left:12px; width:15px; height:15px; color:var(--muted); pointer-events:none; }
.lk-search input { width:100%; height:42px; padding:0 var(--s-5) 0 var(--s-9); font:inherit; font-size:var(--t-md);
  color:var(--ink); background:var(--surface); border:var(--bw) solid var(--line-strong); border-radius:var(--radius); }
.lk-search input::placeholder { color:var(--muted); }
.lk-search input:focus { outline:none; border-color:var(--accent); }

.lk-dice { width:42px; height:42px; flex:none; font-size:var(--t-h3); cursor:pointer; background:var(--surface);
  border:var(--bw) solid var(--line-strong); border-radius:var(--radius); }
.lk-dice:hover { border-color:var(--accent); background:var(--accent-soft); }

.lk-dates { display:flex; align-items:center; gap:var(--s-2); padding:0 var(--s-4); height:42px; flex:none;
  background:var(--surface); border:var(--bw) solid var(--line-strong); border-radius:var(--radius); }
.lk-dates input { width:74px; background:none; border:0; color:var(--ink); font-family:var(--f-mono); font-size:var(--t-mono); text-transform:uppercase; }
.lk-dates input::placeholder { color:var(--muted); }
.lk-dates input:focus { outline:none; color:var(--accent); }
.lk-dsep { color:var(--muted); }

.lk-seg { display:inline-flex; flex:none; height:42px; border:var(--bw) solid var(--line-strong); border-radius:var(--radius); overflow:hidden; }
.lk-seg button { font-family:var(--f-mono); font-size:var(--t-mono); font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  padding:0 var(--s-5); background:var(--surface); color:var(--muted); border:0; border-left:var(--bw) solid var(--line-strong); cursor:pointer; }
.lk-seg button:first-child { border-left:0; }
.lk-seg button.on { background:var(--accent); color:var(--accent-ink); }
.lk-seg button:not(.on):hover { color:var(--ink); }

/* ---------- platform chips ----------
   Each carries its own brand colour, so the row doubles as a legend for the
   tags on the cards below. */
.lk-plats { display:flex; gap:var(--s-2); flex-wrap:wrap; margin-bottom:var(--s-6); }
.lk-chip { display:inline-flex; align-items:center; gap:var(--s-2); padding:var(--s-2) var(--s-4); cursor:pointer;
  font-family:var(--f-mono); font-size:var(--t-label); font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  background:var(--surface); color:var(--muted); border:var(--bw) solid var(--line-strong); border-radius:var(--radius); }
.lk-chip i { width:8px; height:8px; background:var(--p, var(--muted)); border-radius:1px; display:block; }
.lk-chip:hover { color:var(--ink); border-color:var(--p, var(--accent)); }
.lk-chip.on { color:var(--accent-ink); background:var(--accent); border-color:var(--accent); }
.lk-chip.on i { background:var(--accent-ink); }

/* ---------- meta line ---------- */
.lk-meta { display:flex; align-items:center; gap:var(--s-3); flex-wrap:wrap; margin-bottom:var(--s-5);
  font-family:var(--f-mono); font-size:var(--t-mono); color:var(--muted); }
.lk-meta b { color:var(--ink); }
.lk-auto { margin-left:auto; color:var(--muted); }

/* ---------- the grid ---------- */
.lk-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(258px,1fr)); gap:var(--s-5); }

.lk-card { display:flex; flex-direction:column; overflow:hidden; cursor:pointer;
  background:var(--surface); border:var(--bw) solid var(--line-strong); border-radius:var(--radius);
  transition:border-color .15s; }
.lk-card:hover, .lk-card:focus-visible { border-color:var(--p, var(--accent)); outline:none; }

/* The preview area. 16:9 whether or not there is an image, so a row of cards
   never goes ragged because half the archive has no thumbnail. */
.lk-shot { position:relative; aspect-ratio:16/9; background:var(--surface-2); overflow:hidden;
  border-bottom:var(--bw) solid var(--line-strong); display:grid; place-items:center; }
.lk-shot-img { position:absolute; inset:0;
  background:
    linear-gradient(135deg, color-mix(in srgb, var(--p) 40%, transparent), transparent 70%),
    repeating-linear-gradient(45deg, var(--surface-2) 0 8px, color-mix(in srgb, var(--ink) 6%, var(--surface-2)) 8px 16px); }

/* No thumbnail: the domain becomes the artwork. This is the common case, so it
   has to look deliberate rather than broken. */
.lk-shot.none { background:
    linear-gradient(160deg, color-mix(in srgb, var(--p) 16%, transparent), transparent 62%), var(--surface-2); }
.lk-dom-big { position:relative; font-family:var(--f-display); font-weight:900; font-style:italic; text-transform:uppercase;
  font-size:clamp(15px,2.6vw,21px); letter-spacing:-.02em; color:color-mix(in srgb, var(--ink) 42%, transparent);
  padding:0 var(--s-5); text-align:center; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; max-width:100%; }

.lk-play { position:relative; width:40px; height:40px; display:grid; place-items:center; font-size:var(--t-md);
  color:var(--accent-ink); background:var(--p, var(--accent)); border:var(--bw) solid var(--ink); border-radius:var(--radius); }
[data-skin="sweet"] .lk-play { border-color:transparent; }

.lk-tag { position:absolute; top:8px; left:8px; z-index:2; padding:3px var(--s-2);
  font-family:var(--f-mono); font-size:var(--t-micro); font-weight:700; letter-spacing:.1em; text-transform:uppercase;
  color:#0c0c0e; background:var(--p, var(--muted)); border-radius:var(--radius); }

.lk-body { padding:var(--s-4) var(--s-5) var(--s-5); display:flex; flex-direction:column; gap:var(--s-2); flex:1; }
.lk-title { font-family:var(--f-display); font-weight:800; font-size:var(--t-body); line-height:1.3;
  display:-webkit-box; -webkit-box-orient:vertical; -webkit-line-clamp:2; overflow:hidden; }
/* An untitled link shows its URL instead, in mono, so it reads as an address
   rather than as a headline someone wrote. */
.lk-title.untitled { font-family:var(--f-mono); font-weight:700; font-size:var(--t-mono); color:var(--muted); }

.lk-foot { display:flex; align-items:center; gap:var(--s-4); margin-top:auto;
  font-family:var(--f-mono); font-size:var(--t-label); color:var(--muted); }
/* Re-sharing is the archive's own measure of interest, so it is the one number
   given weight. */
.lk-shares-n { display:inline-flex; align-items:baseline; gap:2px; }
.lk-shares-n b { color:var(--accent); font-size:var(--t-body); font-style:italic; font-family:var(--f-display); font-weight:900; }
.lk-when { margin-left:auto; }
.lk-by { font-family:var(--f-mono); font-size:var(--t-micro); letter-spacing:.04em; text-transform:uppercase; color:var(--muted); }
.lk-by b { color:var(--ink); }

.lk-more { display:flex; justify-content:center; margin-top:var(--s-7); }

/* ---------- lightbox ---------- */
.lk-lb { position:fixed; inset:0; z-index:90; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:var(--s-5);
  padding:var(--s-6); background:color-mix(in srgb, var(--bg) 84%, transparent); overflow-y:auto;
  animation:lbBack .22s ease both; }
.lk-lb.shut { display:none; }
@keyframes lbBack { from { background-color:transparent; } }

/* The box arrives a beat after the backdrop, rising slightly, so the two read
   as one movement instead of everything snapping on at once. */
@keyframes lbBox { from { opacity:0; transform:translateY(14px) scale(.985); } }
.lk-lbswitch { animation:lbBox .3s cubic-bezier(.2,.9,.3,1) .1s both; }
.lk-lb-rand { animation:lbBox .3s cubic-bezier(.2,.9,.3,1) .14s both; }
.lk-lb-nav { animation:lbBox .3s ease .16s both; }

/* With the lightbox up, the page behind it must not scroll: reaching the end of
   the share list and carrying on into the grid underneath is disorienting. */
body.lb-open { overflow:hidden; }

.lk-lb-in { display:flex; align-items:flex-start; gap:var(--s-4); width:100%; max-width:1120px; }
.lk-lb-nav { width:38px; height:64px; flex:none; align-self:center; font-size:var(--t-h2); cursor:pointer; color:var(--ink);
  background:var(--surface); border:var(--bw) solid var(--line-strong); border-radius:var(--radius); }
.lk-lb-nav:hover { border-color:var(--accent); color:var(--accent); }

/* align-items:stretch, not start: the side column is as tall as the video
   beside it, which is what lets the share list end exactly where the video
   ends rather than at an arbitrary pixel height. */
.lk-lb-box { position:relative; width:100%; display:grid; grid-template-columns:1.62fr 1fr; align-items:stretch;
  background:var(--surface); border:3px solid var(--accent); border-radius:var(--radius); overflow:hidden; }
@media (max-width:860px){ .lk-lb-box { grid-template-columns:1fr; } .lk-lb-nav { display:none; } }

.lk-lb-player { position:relative; background:var(--surface-2); border-right:var(--bw) solid var(--line-strong); --p:#ff2d55; }
.lk-lb-fake { display:flex; flex-direction:column; align-items:center; justify-content:center; gap:var(--s-5); height:100%;
  aspect-ratio:16/9;
  background:linear-gradient(150deg, color-mix(in srgb, var(--p) 22%, transparent), transparent 60%), var(--surface-2); }

/* TikTok's embed is a fixed portrait frame. Forcing it into a wide box makes it
   scroll inside itself, so the box takes ITS shape instead. */
.lk-lb-player.tiktok { display:grid; place-items:center; padding:var(--s-7) var(--s-6); background:var(--surface); }
.lk-lb-player.tiktok .lk-lb-fake { aspect-ratio:325/738; width:auto; height:min(740px, 78vh); background:
  linear-gradient(150deg, color-mix(in srgb, var(--p) 26%, transparent), transparent 60%), #101014; border-radius:var(--radius); }

/* Reddit posts vary wildly in height and the embed reports its own, so the box
   follows it rather than guessing a ratio. */
.lk-lb-player.reddit .lk-lb-fake { aspect-ratio:auto; min-height:380px; }

.lk-lb-player.nopreview .lk-lb-fake { aspect-ratio:16/9; }
.lk-lb-player.nopreview .lk-lb-play { display:none; }

.lk-lb-x { position:absolute; top:8px; right:8px; z-index:6; width:30px; height:30px; display:grid; place-items:center;
  font-size:var(--t-body); cursor:pointer; color:var(--ink); background:var(--surface);
  border:var(--bw) solid var(--line-strong); border-radius:var(--radius); }
.lk-lb-x:hover { color:var(--accent-ink); background:var(--accent); border-color:var(--accent); }

.lk-lb-plat { position:absolute; top:10px; left:10px; padding:3px var(--s-3); font-family:var(--f-mono); font-size:var(--t-micro); font-weight:700;
  letter-spacing:.1em; text-transform:uppercase; color:#0c0c0e; background:var(--p); border-radius:var(--radius); }
.lk-lb-play { width:54px; height:54px; display:grid; place-items:center; font-size:var(--t-h3);
  color:var(--accent-ink); background:var(--accent); border:var(--bw) solid var(--ink); border-radius:var(--radius); }
[data-skin="sweet"] .lk-lb-play { border-color:transparent; }
.lk-lb-note { font-family:var(--f-mono); font-size:var(--t-micro); letter-spacing:.06em; text-transform:uppercase; color:var(--muted); text-align:center; padding:0 var(--s-6); }

.lk-lb-side { padding:var(--s-6); display:flex; flex-direction:column; gap:var(--s-5); min-width:0; min-height:0; }
.lk-lb-title { font-family:var(--f-display); font-weight:900; font-style:italic; text-transform:uppercase;
  font-size:var(--t-h3); line-height:1.14; letter-spacing:-.01em; margin-top:var(--s-1); }
.lk-lb-title.untitled { font-family:var(--f-mono); font-style:normal; font-weight:700; text-transform:none; font-size:var(--t-body); color:var(--muted); }
/* Open original rides this row, pushed to the right by the gap, because it is
   the one thing you might do with the link and it was previously stranded under
   a scrolling list where it read as a footnote. */
.lk-lb-stats { display:flex; align-items:center; gap:var(--s-6); }
.lk-lb-stats .lk-open { margin-left:auto; }
.lk-stat { display:flex; flex-direction:column; }
.lk-stat b { font-family:var(--f-display); font-weight:900; font-style:italic; font-size:var(--t-h2); color:var(--accent); line-height:1; }
.lk-stat span { font-family:var(--f-mono); font-size:var(--t-micro); letter-spacing:.1em; text-transform:uppercase; color:var(--muted); margin-top:var(--s-1); }

.lk-lb-sec { display:flex; align-items:baseline; justify-content:space-between; gap:var(--s-3);
  padding-bottom:var(--s-2); margin-bottom:2px; border-bottom:var(--bw) solid var(--line); }
.lk-lb-sec small { font-weight:700; letter-spacing:.04em; color:var(--muted); text-transform:none; }

/* ---------- who shared it ----------
   Takes whatever height is left in the column and scrolls inside it, so the
   bottom of the list lands on the bottom of the video no matter how tall the
   video is or how many people shared the link. min-height:0 is what allows a
   flex child to be shorter than its content and therefore to scroll at all. */
.lk-lb-who { flex:1 1 auto; min-height:0; display:flex; flex-direction:column; }
.lk-shares { flex:1 1 auto; min-height:0; display:flex; flex-direction:column; overflow-y:auto; }
/* Stacked, the column has no height to share out, so the list needs a ceiling
   of its own or a heavily shared link runs off the screen. */
@media (max-width:860px){ .lk-shares { max-height:56vh; } }
.lk-sh { border-top:1px solid var(--line); }
.lk-sh:first-child { border-top:0; }
.lk-sh-row { width:100%; display:flex; align-items:baseline; gap:var(--s-3); padding:var(--s-2) 0; cursor:pointer;
  background:none; border:0; color:inherit; text-align:left; font:inherit; }
.lk-sh-row:hover .lk-sh-u { color:var(--accent); }
/* How many times THIS person posted it - the thing the raw list was hiding. */
.lk-sh-n { flex:none; min-width:26px; font-family:var(--f-display); font-weight:900; font-style:italic;
  font-size:var(--t-body); color:var(--accent); }
.lk-sh-u { flex:1; min-width:0; font-weight:700; font-size:var(--t-sm); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.lk-sh-t { font-family:var(--f-mono); font-size:var(--t-micro); color:var(--muted); white-space:nowrap; }
.lk-sh-cv { font-size:var(--t-micro); color:var(--muted); transition:transform .15s; }
.lk-sh.open .lk-sh-cv { transform:rotate(180deg); }

/* Expanding to a height nobody knows in advance. grid-template-rows 0fr -> 1fr
   is the one technique that animates to CONTENT height without measuring it in
   JS, so a person with two messages and a person with twelve both open on the
   same curve. The inner wrapper is what does the clipping. */
.lk-sh-msgs { display:grid; grid-template-rows:0fr; opacity:0;
  transition:grid-template-rows .3s cubic-bezier(.4,.75,.3,1), opacity .22s ease; }
.lk-sh-msgs-in { overflow:hidden; display:flex; flex-direction:column; gap:var(--s-1); padding-left:var(--s-9); }
.lk-sh.open .lk-sh-msgs { grid-template-rows:1fr; opacity:1; }
.lk-sh.open .lk-sh-msgs-in { padding-bottom:var(--s-3); }
/* The messages stagger in behind the opening, so it reads as unfolding rather
   than a block appearing. */
.lk-sh.open .lk-msg { animation:msgIn .26s ease both; }
.lk-sh.open .lk-msg:nth-child(2) { animation-delay:.045s; }
.lk-sh.open .lk-msg:nth-child(3) { animation-delay:.09s; }
.lk-sh.open .lk-msg:nth-child(n+4) { animation-delay:.12s; }
@keyframes msgIn { from { opacity:0; transform:translateY(-4px); } }
/* Zebra striping. Messages wrap to two and three lines, so without a band
   behind them it is genuinely hard to see where one ends and the next starts.
   Deliberately faint: it is a reading aid, not a table. */
.lk-msg { display:flex; align-items:flex-start; gap:var(--s-3); font-size:var(--t-sm); line-height:1.45;
  padding:var(--s-1) var(--s-2); border-radius:calc(var(--radius) - 1px); }
/* The "N distinct out of M" note is a sibling div, so it takes part in the
   count and is excluded from the band below. That shifts which row starts
   banded depending on whether a note is present, which does not matter: the
   job is alternating, not starting on a particular phase. */
.lk-msg:nth-child(odd) { background:color-mix(in srgb, var(--ink) 4%, transparent); }
.lk-msg-t { flex:none; font-family:var(--f-mono); font-size:var(--t-micro); color:var(--muted); padding-top:2px; min-width:38px; }
.lk-msg-m { flex:1; min-width:0; color:var(--ink); word-break:break-word; }

/* A repeat count. One account posted the same link 269 times with a single
   distinct message, so collapsing identical text is the difference between a
   readable list and a wall. */
.lk-msg-c { flex:none; margin-left:auto; min-width:30px; text-align:right;
  font-family:var(--f-mono); font-size:var(--t-micro); font-weight:700; color:var(--accent);
  align-self:flex-start; padding-top:2px; }
.lk-msg-note { background:none !important; }
.lk-msg-note { font-family:var(--f-mono); font-size:var(--t-micro); letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted); padding-bottom:2px; }
.lk-msg-all { align-self:flex-start; margin-top:3px; padding:var(--s-1) 0; cursor:pointer;
  font-family:var(--f-mono); font-size:var(--t-micro); font-weight:700; letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted); background:none; border:0; border-bottom:1px solid var(--line); }
.lk-msg-all:hover { color:var(--accent); border-bottom-color:var(--accent); }
.lk-msg.more { font-family:var(--f-mono); font-size:var(--t-micro); color:var(--muted); padding-left:var(--s-10); }

/* A real button, matching the Random Link control below the lightbox, because
   it is a real action. As accent-coloured text at the bottom of the panel it
   read as a caption on the share list above it. */
.lk-open { flex:none; padding:var(--s-2) var(--s-4); white-space:nowrap;
  font-family:var(--f-mono); font-size:var(--t-micro); font-weight:700; letter-spacing:.1em; text-transform:uppercase;
  color:var(--ink); background:var(--surface); border:var(--bw) solid var(--line-strong); border-radius:var(--radius); }
.lk-open:hover { color:var(--accent); border-color:var(--accent); }
.lk-lb-rand { padding:var(--s-3) var(--s-6); cursor:pointer; font-family:var(--f-mono); font-size:var(--t-mono); font-weight:700;
  letter-spacing:.08em; text-transform:uppercase; color:var(--ink); background:var(--surface);
  border:var(--bw) solid var(--line-strong); border-radius:var(--radius); }
.lk-lb-rand:hover { border-color:var(--accent); color:var(--accent); }

.footer { margin-top:0; }
.footer-in { display:flex; padding:var(--s-6) 0 var(--s-6); }
.foot-note { font-family:var(--f-mono); font-size:var(--t-label); letter-spacing:.05em; text-transform:uppercase; color:var(--muted); }

/* Someone who has asked for less motion gets the states, not the movement. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration:.01ms !important; animation-duration:.01ms !important; animation-iteration-count:1 !important; }
}


/* ============================================================
   REAL-PAGE ADDITIONS

   The mockup's lightbox was static markup with a drawn placeholder. The live
   one injects a real iframe, a real image, or nothing at all, so these are the
   states it could not show.
   ============================================================ */

/* The sandboxed player. Fills whichever shape the platform asked for. */
.lk-lb-player iframe {
  width: 100%; height: 100%; border: 0; display: block; background: #000;
  aspect-ratio: 16/9;
}
.lk-lb-player.tiktok iframe { aspect-ratio: 325/738; height: min(740px, 78vh); width: auto; background: #fff; }
.lk-lb-player.reddit iframe { aspect-ratio: auto; min-height: 380px; background: #fff; }
.lk-lb-player.nopreview iframe { display: none; }

/* Not embeddable, but there IS a picture: show it rather than an empty box. */
.lk-lb-img { width: 100%; height: 100%; object-fit: contain; display: block; }

/* Folded-away messages, once someone asks for all of them. */
.lk-sh-msgs-in.showall { max-height: none; }

/* The grid is replaced wholesale on every filter change, so the cards arrive
   together rather than one at a time. A single quiet fade, not a stagger:
   sixty cards each doing their own entrance is a slot machine. */
.lk-grid { animation: lkGridIn .2s ease both; }
@keyframes lkGridIn { from { opacity: 0; } }

/* ============================================================ CHAT TEXT

   A share message is chat. Two things in it need help that plain escaping
   cannot give.
   ============================================================ */

/* An emote code is a picture, not a word. "posting animal vids Lemn" is not a
   sentence until Lemn renders. */
.lk-emote {
  height: 18px; width: auto; vertical-align: -4px;
  display: inline-block; margin: 0 1px;
}

/* The URL stays, because it is what they typed - but demoted. In a message like
   "https://reddit.com/r/…/i_made_chudjack/ @TenzinNiznet did u see this" the
   address is ninety characters wrapped around the six that are the point, and
   it is also the least informative part: the whole panel is already about that
   link. One line, clipped, muted, so the words win. */
.lk-msg-url {
  display: inline-block; max-width: 100%;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  vertical-align: bottom;
  font-family: var(--f-mono); font-size: var(--t-micro);
  color: var(--muted); opacity: .75;
  border-bottom: 1px solid var(--line);
}
.lk-msg-url:hover { color: var(--accent); opacity: 1; border-bottom-color: var(--accent); }

.lk-msg-empty { color: var(--muted); font-style: italic; }

/* Breathing room before the scrollbar. The counts sat hard against it, which
   read as clipped rather than as a column. */
.lk-shares { padding-right: var(--s-3); }
.lk-sh-msgs-in { padding-right: var(--s-2); }

/* ============================================================ DATE PICKER

   Ours rather than the browser's. A native date input draws its own rounded,
   blue, differently-typefaced widget that ignores the skin completely, which on
   a page made of hard 2px borders reads as a different website.
   ============================================================ */
.lk-dates { position: relative; }
.lk-date {
  min-width: 82px; padding: 0 var(--s-2); cursor: pointer;
  background: none; border: 0; color: var(--muted);
  font-family: var(--f-mono); font-size: var(--t-mono); text-transform: uppercase; letter-spacing: .04em;
}
.lk-date.has { color: var(--ink); }
.lk-date:hover, .lk-date.on { color: var(--accent); }
.lk-dclear {
  width: 20px; height: 20px; flex: none; cursor: pointer; line-height: 1;
  background: none; border: 0; color: var(--muted); font-size: var(--t-md);
}
.lk-dclear:hover { color: var(--accent); }

.dp {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 50; width: 252px;
  padding: var(--s-5); background: var(--surface);
  border: var(--bw) solid var(--ink); border-radius: var(--radius);
  box-shadow: 7px 7px 0 var(--accent);
  animation: dpIn .16s ease both;
}
[data-skin="sweet"] .dp { border-color: transparent; box-shadow: 0 16px 40px var(--shadow); }
@keyframes dpIn { from { opacity: 0; transform: translateY(-6px); } }

.dp-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--s-4); }
.dp-m { font-family: var(--f-display); font-weight: 900; font-style: italic; text-transform: uppercase; font-size: var(--t-body); }
.dp-nav {
  width: 24px; height: 24px; display: grid; place-items: center; cursor: pointer;
  background: transparent; color: var(--ink); border: var(--bw) solid var(--line-strong);
  border-radius: var(--radius); font-size: var(--t-body);
}
.dp-nav:hover { border-color: var(--accent); color: var(--accent); }

.dp-dow { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; margin-bottom: var(--s-1); }
.dp-dow span { text-align: center; font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700; color: var(--muted); }

.dp-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.dp-c {
  aspect-ratio: 1; display: grid; place-items: center; cursor: pointer;
  font-family: var(--f-mono); font-size: var(--t-micro); font-variant-numeric: tabular-nums;
  background: transparent; color: var(--ink); border: 0;
  border-radius: calc(var(--radius) - 1px);
}
.dp-c.empty { cursor: default; }
.dp-c:hover:not(:disabled):not(.empty) { background: var(--accent-soft); color: var(--accent); }
/* Inside the chosen range, so the other end is never a mystery. */
.dp-c.in { background: var(--accent-soft); }
.dp-c.on { background: var(--accent); color: var(--accent-ink); font-weight: 700; }
.dp-c.today { outline: 1px solid var(--line-strong); outline-offset: -1px; }
/* A start after the end is not offered at all, rather than accepted and then
   corrected. */
.dp-c.off, .dp-c:disabled { color: var(--muted); opacity: .3; cursor: not-allowed; }

.dp-foot { display: flex; justify-content: space-between; margin-top: var(--s-4); padding-top: var(--s-3); border-top: 1px solid var(--line); }
.dp-act {
  cursor: pointer; background: none; border: 0; padding: 0;
  font-family: var(--f-mono); font-size: var(--t-micro); font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase; color: var(--muted);
}
.dp-act:hover { color: var(--accent); }

/* ---------- the vault ----------

   THE PANTRY'S, to the millisecond. Both are "a panel opens over a grid of
   cards", and two openings that look different on one site read as two
   different pieces of software. The values here are pantry.css's own.

   The backdrop fades rather than snapping on under the opening doors, and
   fades back out on close, or the dimming vanishes while the doors are still
   shutting. `.closing` has higher specificity than the open rule so it takes
   the animation property outright instead of fighting it. */
.lk-lb.closing { animation: lbBackOut 0.42s ease both; }
@keyframes lbBackOut { to { background-color: transparent; } }

/* The stage is exactly the card's box, so the doors are sized to it rather
   than to the whole screen. */
.lk-lb-stage { position: relative; flex: 1; min-width: 0; }
.lk-lb-clip { clip-path: inset(0 0 0 0); will-change: clip-path; }

/* OUTSIDE the clip. clip-path clips an element's border along with everything
   else, so the card's own top and bottom edges do not exist until the reveal
   finishes; this box opens on the same curve and gives the seam a lit edge the
   whole way down. */
.lk-lb-frame {
  position: absolute; left: 0; right: 0; top: 0; bottom: 0;
  border: 3px solid var(--accent);
  border-radius: var(--radius);
  pointer-events: none;
  z-index: 2;
}
[data-skin="sweet"] .lk-lb-frame { border-color: transparent; box-shadow: 0 22px 60px var(--shadow); }
