/* ===========================================================
   technologybrief — lists.css

   The email-capture list pages: /websites now, and /apps,
   /commands, /products and /cheatsheet after it. One look, shared
   by every one of them; each page brings only its own words and
   its own rows. See "List pages" in DESIGN.md.

   This file is versioned on its own (?v= on the list pages only),
   so a change here never means touching the other 380 pages.
   Everything it can borrow from styles.css it borrows: the page
   head, the email box, the chips, the search box, the buttons.
   =========================================================== */

/* A visitor who already gave their email on this device: the head
   script marks <html> before anything paints, so the form never
   flashes up and then vanishes. lists.js opens the list itself. */
html[data-list-known] [data-list-locked]{display:none}

/* ---------- the locked state ---------- */
.list-lock{padding-bottom:clamp(56px,8vh,96px)}
.list-form{margin:0}
@media (max-width:560px){
  .list-form{flex-direction:column}
  .list-form .field-wrap{min-width:0}
  .list-form .btn{width:100%}
}

/* ---------- the Telegram plug (brief 19) ----------
   Under the email box, before the email only. When it first comes on
   screen (lists.js adds .is-on) the line types itself out behind a
   green caret, the button rises in just after the last letter, a
   green square stamps where the full stop would be, then one light
   runs once round the button and fades. Only opacity,
   transform and visibility move, so the form above never shifts.
   lists.js marks it .is-ready once the line is split into letters;
   until then a page with scripts shows nothing, and a page whose
   script never arrives shows the finished plug after three seconds. */
.plug{position:relative;margin-top:clamp(48px,7vh,80px);padding-top:clamp(36px,5vh,56px);border-top:1px solid var(--line-soft);--type:55ms}
@media (scripting:enabled){
  .plug:not(.is-ready){opacity:0;animation:plug-failsafe .4s 3s forwards}
}
@keyframes plug-failsafe{to{opacity:1}}
/* On a phone the page head sits closer under the nav and the plug
   closer under the form, so the email box and the plug both make the
   first screen (Alden, October 10). */
@media (max-width:560px){
  .page-head{padding-top:96px}
  .plug{margin-top:32px;padding-top:28px}
}
/* Everything waits, frozen on its first frame, until it is on screen. */
.plug.is-ready:not(.is-on) *,.plug.is-ready:not(.is-on) *::before,.plug.is-ready:not(.is-on) *::after{animation-play-state:paused !important}

.plug-line{font-size:clamp(36px,5.6vw,72px);font-weight:300;letter-spacing:var(--tight);line-height:1.04;text-transform:lowercase;max-width:15ch;margin:0;text-wrap:balance}
/* "telegram" is green only, the line's own weight (Alden, October 26) */
.plug-line b{font-weight:inherit;color:var(--accent)}
/* /newsletter has the same plug, in its centred block (OPEN-IDEAS 71) */
.news .plug{text-align:center}
.news p.plug-line{font-size:clamp(36px,5.6vw,72px);line-height:1.04;color:var(--fg);max-width:15ch;margin:0 auto}
/* /newsletter has no page head (Alden, October 26): its block starts where
   the head would, and its title is the page's h1, sized as the h2 it was. */
.news-top{padding-top:132px}
@media (max-width:560px){.news-top{padding-top:96px}}
.news h1{font-size:clamp(32px,5vw,64px);margin:0 0 16px;text-wrap:balance}
.plug .w{display:inline-block;vertical-align:top;white-space:nowrap}
.plug .ch{position:relative}
/* the caret: each letter carries it for the moment it is the newest */
.plug .ch::after{content:'';position:absolute;left:100%;bottom:.1em;width:.055em;height:.74em;margin-left:.02em;background:var(--accent);opacity:0}
/* the green square that ends the line, as it ends the wordmark */
.plug-sq{display:inline-block;width:.15em;height:.15em;background:var(--accent);margin-left:.09em}

.plug-cta{position:relative;display:inline-flex;margin-top:clamp(28px,4vh,40px);border-radius:999px;isolation:isolate}
.plug-btn{font-size:17px;padding:18px 32px;gap:12px}
@media (max-width:560px){
  .plug-cta{display:flex}
  .plug-btn{width:100%;padding:18px 24px}
}
/* the light that runs round the button's edge, once */
@property --plug-a{syntax:'<angle>';inherits:false;initial-value:0deg}
.plug-cta::before{content:'';position:absolute;inset:-3px;z-index:-1;border-radius:inherit;background:conic-gradient(from var(--plug-a),transparent 0 58%,rgba(15,255,80,.9) 78%,#fff 84%,transparent 88%);filter:blur(2.5px);opacity:0;pointer-events:none}

@keyframes plug-show{from,to{visibility:hidden}}
@keyframes plug-caret{from,to{opacity:1}}
@keyframes plug-blink{0%,49.9%{opacity:1}50%,100%{opacity:0}}
@keyframes plug-stamp{0%{transform:scale(.3);opacity:0}45%{transform:scale(1.6);opacity:1}100%{transform:scale(1);opacity:1}}
@keyframes plug-up{from{opacity:0;transform:translateY(16px);filter:blur(4px)}to{opacity:1;transform:none;filter:none}}
@keyframes plug-edge{0%{opacity:0;--plug-a:0deg}9%,86%{opacity:1}100%{opacity:0;--plug-a:360deg}}

/* A phone that asks for less motion gets the finished plug, still. */
@media (prefers-reduced-motion:no-preference){
  .plug.is-ready .ch{animation:plug-show 1ms linear backwards;animation-delay:calc(300ms + var(--c) * var(--type))}
  .plug.is-ready .ch::after{animation:plug-caret var(--type) linear;animation-delay:calc(300ms + var(--c) * var(--type))}
  .plug.is-ready .ch.is-last::after{animation:plug-blink .9s linear 2;animation-delay:calc(300ms + var(--c) * var(--type))}
  .plug.is-ready .plug-sq{animation:plug-stamp .5s var(--ease) backwards;animation-delay:calc(2100ms + var(--nc) * var(--type))}
  /* the button: 0.2s after the last letter is typed */
  .plug.is-ready .plug-cta{animation:plug-up .8s var(--ease) backwards;animation-delay:calc(500ms + (var(--nc) - 1) * var(--type))}
  .plug.is-ready .plug-cta::before{animation:plug-edge 3.2s linear;animation-delay:calc(2400ms + var(--nc) * var(--type))}
}

/* ---------- the open state ---------- */
.list-open{padding-bottom:clamp(64px,9vh,104px)}
.list-open:focus{outline:none}
@media (prefers-reduced-motion:no-preference){
  .list-open{animation:list-in .7s var(--ease) both}
}
@keyframes list-in{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}

.list-save{display:flex;align-items:center;gap:12px 20px;flex-wrap:wrap;margin-bottom:clamp(36px,5vh,56px)}
.list-save .form-note{margin:0}
.list-save .btn svg{flex:0 0 auto}
@media (max-width:560px){.list-save .btn{width:100%}}

.list-open .filterbar{margin-top:0}
@media (max-width:560px){.list-open .search{flex:1 1 100%;min-width:0}}

/* ---------- a category and its rows ---------- */
.list-group{margin-top:clamp(40px,6vh,64px)}
.list-group:first-child{margin-top:0}
.list-group-title{display:flex;align-items:baseline;gap:12px;font-size:clamp(24px,2.6vw,34px);margin:0 0 18px}
.list-group-n{font-size:13px;font-weight:500;letter-spacing:0;color:var(--dim)}

.list-rows{list-style:none;margin:0;padding:0;border-top:1px solid var(--line-soft)}
/* sub-headings inside a category, for lists that have them (commands) */
.list-section + .list-section{margin-top:clamp(28px,4vh,40px)}
.list-sub{font-size:12px;font-weight:500;letter-spacing:.14em;text-transform:uppercase;line-height:1.4;color:var(--dim);margin:0 0 12px}
.list-row{display:grid;grid-template-columns:minmax(0,1fr);grid-template-areas:"main" "what" "price" "more";gap:6px;padding:20px 0 22px;border-bottom:1px solid var(--line-soft)}
@media (min-width:860px){
  .list-row{grid-template-columns:minmax(0,1fr) minmax(0,2.2fr) minmax(0,.9fr);grid-template-areas:"main what price" "main more price";gap:6px clamp(24px,3vw,48px);padding:24px 0 26px}
  [data-list-noprice] .list-row{grid-template-columns:minmax(0,1fr) minmax(0,2.4fr);grid-template-areas:"main what" "main more"}
}
.list-main{grid-area:main;display:flex;flex-direction:column;gap:3px;min-width:0}
.list-name{font-size:clamp(17px,1.4vw,19px);font-weight:500;letter-spacing:-.02em;line-height:1.25;text-transform:none;margin:0;overflow-wrap:anywhere}
.list-name a{transition:color .2s}
.list-name a:hover{color:var(--accent)}
.list-name .list-ext{display:inline-block;margin-left:6px;font-size:.8em;color:var(--dim);transition:color .2s,transform .22s var(--ease)}
.list-name a:hover .list-ext{color:var(--accent);transform:translate(2px,-2px)}
.list-url{font-size:13px;color:var(--dim);overflow-wrap:anywhere}
.list-what{grid-area:what;font-size:15px;line-height:1.5;color:var(--dim);max-width:62ch;margin:0}
.list-price{grid-area:price;font-size:14px;font-weight:500;line-height:1.4;margin:4px 0 0}
@media (min-width:860px){.list-price{margin:0}}
.list-more{grid-area:more;display:flex;flex-direction:column;gap:4px;margin-top:6px}
.list-more p{font-size:13px;line-height:1.5;color:var(--dim);max-width:62ch;margin:0;overflow-wrap:anywhere}
.list-k{font-size:11px;font-weight:500;letter-spacing:.14em;text-transform:uppercase;color:var(--dim);margin-right:8px}

/* ---------- nothing matches ---------- */
.list-none{text-align:center;padding:64px 0 72px;border-top:1px solid var(--line-soft)}
.list-none p{color:var(--dim);margin:0 0 22px}

/* ---------- the foot of the list ---------- */
.list-end{display:flex;flex-direction:column;align-items:flex-start;gap:16px;margin-top:clamp(48px,7vh,80px)}
.list-end p{font-size:clamp(20px,2vw,26px);letter-spacing:-.02em;margin:0}
@media (max-width:560px){.list-end .btn{width:100%}}
