/*
 * web.css -- website-only styling, loaded after taskpane.css.
 *
 * The first web-only file. It exists because the two shells have started to
 * diverge visually, and the alternative -- editing taskpane.css and having
 * the change land in Word too -- is exactly what the shared-core arrangement
 * is meant to prevent. Anything here applies to the WEBSITE ONLY. The Word
 * pane never loads this file.
 */

/*
 * FULL-STRENGTH HAMSTER, his ruling 2026-08-11: "get rid of all transparency
 * for the hamster and the wordmark on the website." Restated 2026-08-16: "I
 * want it to be 100%."
 *
 * THE WATERMARK IDEA IS RETIRED -- do not reason from it again. Both marks
 * were once faint (0.46, and 0.34/0.41 in dark) on the argument that in Word
 * they sit behind a working panel and must not compete with the rhymes. That
 * is no longer true anywhere: taskpane.css took the WORD PANE to full opacity
 * on 2026-08-15, and this file has held the website at full opacity since
 * 2026-08-11. His words on the old rationale, 2026-08-16: "a reference to an
 * old note that was superseded. don't want it as a watermark anymore."
 *
 * So this rule is now agreement rather than divergence, and it is kept
 * deliberately: it is what guarantees the WEBSITE stays at full strength if
 * the shared file is ever dialled back for Word again. The only transparency
 * note left in this area that is still live is the dark-mode
 * `brightness(1.9)` on the wordmark in taskpane.css -- and that is a
 * brightness lift for a two-tone PNG on a dark ground, not transparency.
 */
/* ::after is no longer named here: the lockup wordmark under the hamster was
   dropped on every surface 2026-08-18 (see taskpane.css). Only the hamster
   remains on the startup screen. */
#out.startup::before {
  opacity: 1;
}

/*
 * THE GREETING, a step darker on the web, his ruling 2026-08-11.
 *
 * taskpane.css puts it at --muted (#605e5c) because inside Word it is one
 * quiet line in a working panel. On the website it is the first sentence
 * anybody reads, sitting alone on an empty screen, and --muted reads as
 * disabled text there. Nudged toward --fg without reaching it: it says the
 * thing is alive, but it is still not a heading. The count underneath stays
 * at --faint -- the contrast between the two lines is the point.
 */
.status .greeting { color: #3d3b39; }

/* ---------- phone fixes, his report 2026-08-11 ---------- */

/*
 * "It zooms in a bit on the page when I select the search bar."
 *
 * That is iOS Safari, and it is not arbitrary: it zooms whenever a focused
 * input has a font-size UNDER 16px, on the theory that it is helping you
 * read. taskpane.css sets the body to 14px and #q inherits it, so the box is
 * 14px and every tap on it zooms the page. Nothing zooms back afterwards,
 * which is why the results then ran off the right-hand edge.
 *
 * 16px is the whole fix. It is scoped to coarse pointers -- touchscreens --
 * so the desktop box keeps the 14px proportions the pane was designed at, and
 * the Word pane is untouched either way.
 *
 * The other standard "fix" for this, maximum-scale=1 in the viewport meta,
 * is deliberately NOT used: it stops the page zooming on focus by stopping
 * the page zooming AT ALL, including for someone who is pinching because
 * they need to. Fixing our layout problem by removing their zoom is not a
 * trade worth making.
 */
@media (pointer: coarse) {
  #q { font-size: 16px; }
}

/*
 * NO DOUBLE-CLICK TOGGLE ON THE WEB, his ruling 2026-08-11: "it doesn't apply
 * here." Correct -- #dblbtn governs onSelectionChanged, which fires when you
 * double-click a word in a WORD DOCUMENT. There is no document on the
 * website, so the button toggles nothing. Hidden rather than removed, so
 * taskpane.js can go on wiring it up and reading it without knowing.
 */
#dblbtn { display: none; }

/*
 * PHONE TYPE SCALE, his ruling 2026-08-11: "tick up the size of every word a
 * tiny bit. They are all too small."
 *
 * Every size in taskpane.css was chosen against a ~320px Word panel viewed on
 * a desktop monitor at arm's length. A phone is smaller, held closer, and has
 * no panel chrome around it -- 10px section labels that read as quiet on a
 * monitor read as unreadable in the hand. This is a flat ~10% lift of the
 * whole scale, not a redesign: every relationship between the sizes is
 * preserved, so nothing changes rank.
 *
 * Phones only (below 768px). Desktop keeps the proportions the pane was drawn
 * at, and the Word pane never sees this file.
 */
@media (max-width: 767px) {
  html, body        { font-size: 15.5px; }   /* the rhyme words themselves */
  .headword         { font-size: 19px; }
  h2                { font-size: 12px; }     /* "2 SYLLABLES" */
  .count            { font-size: 11.5px; }
  .secdot           { font-size: 14px; }
  footer            { font-size: 12px; }

  .sensetab         { font-size: 13px; }
  .sensetab-n       { font-size: 11px; }
  .sensecap         { font-size: 11.5px; }

  .stretchopen,
  .stretchhint,
  .stretchcap       { font-size: 11.5px; }

  /* was 11.5px -- stepped back down 2026-08-15 ("slightly less prominent"
     on mobile); the base opacity .7 from taskpane.css applies here too */
  .addopen          { font-size: 10.5px; }
  .addword          { font-size: 14.5px; }
  .addsyl           { font-size: 13px; }
  .addsave,
  .addcancel        { font-size: 12px; }
  .addpreview       { font-size: 11.5px; }

  #options,
  #blockpanel,
  #confirm,
  #manualtext       { font-size: 13px; }
  #blockhead,
  .blockundo,
  #confirm button,
  #undoblock,
  #manualclose,
  #flapdesc,
  #tray button,
  #familygroup > summary,
  #loosegroup > summary,
  #othergroup > summary { font-size: 12px; }
}

/* ---------- the wordmark, and the results box ---------- */

/*
 * THE WORDMARK sits above the search bar on every page, his ruling. Centred
 * over the column, small enough that it is a signature rather than a banner.
 * The asset is 196x38, so 150px is inside its native size and stays sharp.
 */
/*
 * AS BIG AS IT FITS, his ruling 2026-08-11: "make the wordmark as large as it
 * can comfortably be, squeezing out extra space" -- WITHOUT moving the search
 * box down.
 *
 * So it is a fixed height budget, not a free choice. The box sat 51px from
 * the top of the header: 10px header padding + 2px above the mark + 29px of
 * mark + 10px below it. The same 51px now goes 5 + 0 + 40 + 6, which buys
 * 11px of mark -- about a third larger -- and the search box has not moved a
 * pixel.
 *
 * 205px is a whisker over the asset's native 196px. Anything much past that
 * starts to soften, and a blurry wordmark is worse than a small one; if he
 * wants it bigger again the answer is a bigger PNG, not a bigger number here.
 */
/*
 * THE BANNER BAND, his artwork (Wordclouds.com, 2000x200 PNG).
 *
 * THE ARTWORK IS NOT AS WIDE AS ITS CANVAS. Measured column by column in the
 * browser: ink covers pixels 3-1472 and the last 527 are empty -- 91-94%
 * coverage across the first seven tenths, then 0%. So the file is 2000 wide
 * and the cloud is 1470 wide, which is why the band first appeared to stop
 * short on the right. Nothing to do with the CSS.
 *
 * Cropping it with sips was tried and cost content off the LEFT edge, so the
 * fix is here instead: no-repeat, and the position shifts the image so the
 * CLOUD is centred rather than the canvas.
 *
 * The number is +262px and it is worth showing the arithmetic, because the
 * obvious guess is wrong. A percentage in background-position is measured
 * against (container - image), NOT the container: left = (C - 2000) * 50% + L.
 * We want the ink's midpoint (738 of 2000) at the container's midpoint, i.e.
 * left = C/2 - 738. Solving gives L = +262px. The first attempt used
 * calc(50% - 738px) and shoved the cloud into the left third of the window.
 *
 * A window wider than ~1470px shows bare page at the edges. That is honest --
 * the artwork is only that wide -- and the cloud's edges are soft enough that
 * it reads as a centred banner rather than a cut-off one. The real fix is a
 * re-export that fills its canvas.
 *
 * Natural size, never scaled: widen the window and more cloud appears, narrow
 * it and the edges crop.
 *
 * THE BREAKPOINT WAS 768px UNTIL 2026-08-13, and his ruling moved it to 480:
 * "when I look at the page in a more narrow form on the computer, the banner
 * just vanishes ... I want it there!" A narrowed desktop window and a phone
 * are the same thing to CSS, so the old rule could not tell them apart and
 * took the band away from both.
 *
 * 480 rather than 0, and the reason is legibility, not screen budget. Below
 * 768 the header is NOT sticky (see the #rhtop block further down, which is
 * still gated at 768), so the band scrolls away like any other scenery and
 * costs nothing permanent -- the original worry does not apply down here.
 * What does apply is that the artwork never scales: the window is a fixed
 * window onto a 1470px-wide cloud, so the narrower it gets the fewer words
 * are in it. At 480 that is a 480px slice, minus 60px of fade at each end,
 * which is still a legible piece of cloud. Much below that it is a smudge.
 *
 * One number if he wants it on portrait phones too -- and it would scroll
 * away there, not pin.
 */
#rhband { display: none; }

/*
 * ALL THREE 480px GATES BELOW WENT TO 0 ON 2026-08-14, his ruling: "lock the
 * header when we scroll down, just like on the desktop site (both portrait
 * and landscape). I'd also like to add the banner on the portrait mobile
 * site, too, in the same location -- from the top of screen to the middle of
 * the search bar." That is exactly what band + pin + lift already build, so
 * the phones simply join the design instead of getting their own. The old
 * floor's worry (a sub-480 slice of cloud is a smudge) is overridden.
 */
@media (min-width: 0px) {
  #rhband {
    display: block;
    position: relative;
    /* 120px, then 20% off the TOP on his ruling -- 96px. The art is still
       drawn 200 tall; this crops it. */
    height: 96px;
  }

  /*
   * PHONE PORTRAIT HAS NO BAND AT ALL -- his rulings 2026-08-15, walked down
   * the same day: 60%, 40%, 30%, then off ("let's just not use the banner at
   * all, which means we can scooch everything up"). Landscape keeps the full
   * 96 -- he called it great there. The bar-LIFT is cancelled with the band
   * (see the block that sets it: "the lift exists so half the bar covers the
   * banner, which is meaningless without a banner"), so the header sits at
   * the very top and the whole page moves up by band + lift. The sticky
   * header stays -- pinning was never the band's.
   */
  @media (max-width: 479px) {
    #rhband { display: none; }
  }

  /*
   * The artwork is a PSEUDO-ELEMENT, not the band's own background, so its
   * transparency can be turned down without taking the wordmark with it.
   * opacity on #rhband would fade both.
   */
  #rhband::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: url("banner.png");
    background-repeat: no-repeat;
    /* -64px, not `center`: centring would have trimmed 12px off the top AND
       12px off the bottom. He asked for the top only, so the vertical offset
       pins the same bottom edge the 120px band had (art row 160) and takes
       the whole 24px out of the top. */
    background-position: calc(50% + 262px) -64px;
    background-size: 2000px 200px;
    /*
     * 80% opaque was his first call; 70% the next, once the cream came off;
     * 85% now, on "bump up the opaqueness of the header a bit".
     *
     * 85 is not a guess at "a bit". The 2026-08-13 word cloud is FAINTER ART
     * than the one it replaced -- its darkest ink measures alpha 209 where
     * the old file reached 255, with 38,880 pixels above 224 in the old one
     * and none at all in the new. At 0.7 the band was therefore reading about
     * 18% lighter than the banner he had approved. 0.7 x 255/209 = 0.85 puts
     * the darkest ink back exactly where it used to sit, so this restores a
     * weight he already signed off rather than inventing one.
     */
    opacity: 0.85;
    /*
     * EDGES DISSOLVE, his ruling 2026-08-13: "the right and left edges of the
     * banner slowly fade to white ... it just sort of disappears into the
     * white."
     *
     * THIS IS HALF THE JOB, and it is worth knowing which half. This mask
     * fades the BAND's edges, which are the SCREEN's edges -- the case below
     * about 1476px, where the window is narrower than the 2000px artwork and
     * the screen crops straight through the middle of the cloud.
     *
     * Above 1476px the art stops short of the screen on its own: at 1920 the
     * words begin 228px in and end 228px early. There this mask is fading
     * blank white while the artwork's real edge sits untouched in the middle
     * of the band. That edge is faded in the PNG instead, by
     * tools_edgefade.py, with a ramp that travels with the art. Neither one
     * covers both cases; together they cover every width.
     *
     * 120px, not a percentage: the fade should be the same width on a laptop
     * and a 4K monitor, and a percentage would make it four times longer on
     * the second.
     */
    -webkit-mask-image: linear-gradient(to right, transparent 0,
                                        #000 120px, #000 calc(100% - 120px),
                                        transparent 100%);
    mask-image: linear-gradient(to right, transparent 0,
                                #000 120px, #000 calc(100% - 120px),
                                transparent 100%);
  }

  /*
   * THE WORDMARK ON THE BAND. Centred, larger than the header version, and
   * carrying a heavy white bloom so it reads against whatever words sit
   * underneath it.
   *
   * Stacked drop-shadows, not one: a single shadow at this radius goes thin
   * and grey. Four passes at increasing radius build an actual halo -- the
   * tight ones give the hard edge that separates the letterforms, the wide
   * one clears a soft field around the whole mark. text-shadow is no use
   * here; the wordmark is a PNG, so the glow has to come from a filter that
   * follows its alpha.
   */
  #rhband #rhmark {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    line-height: 0;
    /*
     * "Scooch the wordmark up a tiny bit, it's a hair too close to the search
     * box." Measured before moving: 19px of air above the mark and ONE pixel
     * below it, because the search bar now slides up into the band's bottom
     * 18px and the mark was still centring itself on the whole band.
     *
     * Padding on the flex box rather than a transform or a negative margin:
     * centring inside a shorter box moves the mark up by half the padding
     * without taking it out of the layout, so the halo still has room to
     * bloom on every side. 18px of padding = 9px of lift, which splits the
     * air evenly -- 10 above, 10 below.
     */
    padding-bottom: 18px;
  }

  #rhband #rhmark img {
    /*
     * 240 -> 300 on "make the wordmark bigger", then 300 -> 270 on "shrink
     * the wordmark a tad", 2026-08-13. A tad, so a tenth.
     *
     * This direction costs nothing, which the other one did: the asset is
     * 196px native, so 300 was upscaling it by half and softening the
     * letterforms. 270 is still above native and still slightly soft -- if he
     * ever wants it crisp at this size the answer is a bigger PNG, not a
     * different number here.
     */
    width: 270px;
    max-width: 46%;
    filter:
      drop-shadow(0 0 4px #fff)
      drop-shadow(0 0 10px #fff)
      drop-shadow(0 0 22px rgba(255, 255, 255, 0.95))
      drop-shadow(0 0 40px rgba(255, 255, 255, 0.8));
  }
}

/*
 * THE BAND, SLIMMED FOR NARROW WINDOWS (480-767px).
 *
 * Only three things change, and the search bar's overlap is deliberately not
 * one of them: the bar sits at header-top + 5px of padding, and the header is
 * pulled up 23px from the band's BOTTOM edge, so the 18px of overlap he asked
 * for falls out of those two numbers alone and holds at any band height.
 * Verified at 1280, 900, 600 and 500.
 *
 * The vertical offset moves WITH the height for the same reason it was -64 at
 * 96px tall: the band's bottom edge is pinned to art row 160, so a 76px band
 * has to start at row 84. Leaving it at -64 would have cropped the extra 20px
 * off the bottom of the cloud instead of the top, which is the opposite of
 * what he ruled.
 *
 * The edge fade halves to 60px because 120px of fade at each end of a 500px
 * band leaves 260px of actual cloud in the middle -- the fade would have been
 * most of the banner.
 */
@media (min-width: 480px) and (max-width: 767.98px) {
  #rhband { height: 76px; }

  #rhband::before {
    background-position: calc(50% + 262px) -84px;
    -webkit-mask-image: linear-gradient(to right, transparent 0,
                                        #000 60px, #000 calc(100% - 60px),
                                        transparent 100%);
    mask-image: linear-gradient(to right, transparent 0,
                                #000 60px, #000 calc(100% - 60px),
                                transparent 100%);
  }
}

header { padding-top: 5px; }

/*
 * THE HEADER STAYS PUT, his ruling 2026-08-11: "keep everything above the
 * horizontal line locked in place, so I can see the search bar (and
 * wordmark)... the words will sort of scroll UNDER that header section."
 *
 * Sticky, not fixed. Fixed takes the header out of the flow, so the results
 * box slides up underneath it on load and needs a matching top margin to
 * compensate -- a number that then has to be kept in sync with the wordmark's
 * size forever. Sticky leaves it in the flow and pins it only once the page
 * starts moving, so there is nothing to maintain.
 *
 * It needs its own background, because the words genuinely do pass beneath
 * it, and it needs to sit above them in the stack. The border-bottom that was
 * already there becomes the line he is describing: the edge the list
 * disappears under.
 *
 * 480px UP, matching the band, on his ruling 2026-08-13: "I want to lock
 * everything above the horizontal line in place as a header as I scroll down
 * on the desktop." It was 768 until then, on the argument that a phone gives
 * up a much bigger share of a short screen -- but a narrowed desktop window
 * reads as 600px to CSS just as a phone does, and he is working in one. The
 * floor stays at 480 so a portrait phone still scrolls the whole thing away.
 */
@media (min-width: 0px) {
  /*
   * THE WHOLE TOP PINS AS ONE PIECE, his ruling: banner, search bar and the
   * rule underneath it all stay put together.
   *
   * The BLOCK carries the opaque background, not the header. The band's
   * artwork is only 70% opaque and sits on a ::before, so without a solid
   * backdrop here the rhyme list would scroll visibly through the banner.
   * With it, the header itself can stay transparent -- which is what lets the
   * band show through in the gutters either side of the search bar.
   */
  #rhtop {
    position: sticky;
    top: 0;
    z-index: 20;
    background: var(--bg);
    /*
     * SAFARI, his report 2026-08-13: "it's the deployed website. I'm using
     * safari. it doesn't matter how narrow the window is, the header doesn't
     * stick" -- and, separately, "the header works on chrome".
     *
     * The cause is not this rule, it is the CONTAINER. taskpane.css makes
     * <body> a column flex box because Word's pane needs header/main/footer to
     * fill a fixed-height panel, so #rhtop is a flex ITEM. Safari has a
     * long-standing bug where position:sticky does nothing on a flex item that
     * is being stretched on the cross axis -- which is the default, and which
     * is why this works in Chrome and not in Safari.
     *
     * align-self:flex-start takes it out of the stretch, and width:100% puts
     * back the full-bleed the stretch was giving it. Chrome renders this
     * identically; it is Safari that needs it.
     */
    align-self: flex-start;
    width: 100%;
  }
}

/*
 * THE SEARCH BAR'S LIFT BELONGS TO THE BAND, NOT TO THE STICKY HEADER.
 *
 * These two rules used to live inside the 768px block above, and when the
 * band's breakpoint moved to 480 on 2026-08-13 they did not come with it --
 * so between 480 and 767 the band appeared correctly and the bar sat 5px
 * BELOW it instead of 18px into it. Measured at 600px: a -5px overlap where
 * the design calls for +18.
 *
 * They are down here, at the band's own breakpoint, because that is what they
 * are for: the lift exists so half the bar covers the banner, which is
 * meaningless without a banner and required whenever there is one. Pinning is
 * a separate question and stays at 768 -- his framing, since giving up the
 * top of a short screen permanently is a different trade.
 */
@media (min-width: 480px) {
  header {
    background: transparent;
    /* Half the 36px bar plus the header's 5px padding: the overlap he asked
       for, measured rather than guessed. */
    margin-top: -23px;
  }
}

#rhmark {
  display: block;
  text-align: center;
  margin: 0 0 6px;
  line-height: 0;
}

#rhmark img {
  width: 205px;
  max-width: 62%;
  height: auto;
}

/*
 * THE RESULTS BOX, his design ruling 2026-08-11: the found words live in a
 * box that "extends allllll the way to the end of the entry", sharing the
 * search bar's visual language -- same width, same fill, same border.
 *
 * That last clause is the structural part: a box that ends where the ENTRY
 * ends is a box whose height is its content, which means the PAGE has to
 * scroll rather than the results pane. taskpane.css does the opposite -- it
 * pins html/body to 100% and scrolls #out inside a fixed frame, which is
 * right in a Word panel that must never grow. Undone here, and only here.
 */
html { height: auto; }

/* 100vh, not 100%: with html at auto height a percentage resolves to auto and
   the footer rides up under a short entry instead of sitting at the bottom
   of the window. */
body { height: auto; min-height: 100vh; }

/*
 * The box carries the column itself, with width + auto margins, rather than
 * the padding trick the header and footer use. Those two need the column
 * INSIDE a full-width band, because their rules are the frame of the app; the
 * box is the opposite -- it is an object on the page, and its edges are the
 * thing you are meant to see.
 */
main {
  overflow: visible;
  /* taskpane.css gives it flex:1 so it fills the Word panel. Here it must be
     exactly as tall as the entry -- that is the whole point of the box. */
  flex: 0 0 auto;
  width: min(640px, 100% - 24px);
  /*
   * CENTRED WITH align-self, NOT auto margins -- his report 2026-08-13: "the
   * panel with the words on it is no longer centered when i stretch the
   * window", Safari only, Chrome fine.
   *
   * Same root cause as the sticky header above: <body> is a column flex box,
   * so this is a flex item and the horizontal axis is the CROSS axis. It used
   * to centre with `margin: 14px auto 18px`, which relies on auto-margin
   * resolution against a min() width in a stretched flex item -- the exact
   * combination Safari gets wrong. align-self:center is the flex-native way to
   * say the same thing and does not depend on the margin pass at all.
   */
  align-self: center;
  margin: 14px 0 18px;
  background: var(--field);
  border: 1px solid var(--rule);
  border-radius: 4px;
  padding: 12px 14px 16px;
}

/*
 * The footer was the last row of a full-height flex column; with the page
 * scrolling it would otherwise ride up under short results. Stuck to the
 * bottom of the window, where it was before, with the page's own background
 * behind it so the word list does not show through.
 */
footer {
  /* Pushed to the bottom of the window when the entry is short, and stuck
     there while a long one scrolls past behind it. */
  margin-top: auto;
  position: sticky;
  bottom: 0;
  background: var(--bg);
}

/*
 * THE POPUPS HAVE TO BE FIXED, NOT ABSOLUTE -- a regression I caused and
 * caught while checking the sticky header, not something he reported.
 *
 * taskpane.css anchors #options and #blockpanel with `position: absolute;
 * bottom: 34px`, which in Word means "34px above the bottom of the pane",
 * because the pane is exactly one screen tall and body is the containing
 * block. On the web the body is now as tall as the entry -- 3,000px for
 * 'day' -- so "34px from the bottom of body" is 34px from the bottom of the
 * DOCUMENT. The gear popup was opening 2,400px below the viewport: it worked,
 * it just did it somewhere nobody was looking.
 *
 * Fixed positioning re-anchors both to the viewport, which is where the
 * footer they belong to now lives (it is sticky). Web only; in Word the
 * absolute version is still exactly right.
 */
#options,
#blockpanel {
  position: fixed;
}

/*
 * #confirm HAS THE SAME DISEASE, found 2026-08-15 when he reported the
 * block button "doesn't pop up and nothing happens" with words gathered.
 * The handler fires and the bar unhides -- at its place in the document
 * flow, which on the web is BELOW the whole word list. Blocking two words
 * from the top of 'heart' put the confirmation 3,000px under the viewport:
 * it worked, it just did it somewhere nobody was looking, exactly like the
 * popups above. Pinned to the viewport bottom, over the footer -- a confirm
 * is a modal moment, so covering the footer's buttons while it asks is
 * right, not rude. #manual (the copy fallback) rides along: same element
 * class, same flow position, same disease.
 */
#confirm,
#manual {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 45;
  box-shadow: 0 -2px 10px rgba(0, 0, 0, .10);
  padding-bottom: calc(8px + env(safe-area-inset-bottom, 0px));
}

/*
 * The startup screen is the one place the box is wrong: the hamster is a
 * picture on an empty page, not an entry, and framing him in a data box makes
 * the front door look like a form. Kept flush until there is something in it.
 */
main.startup {
  background: none;
  border-color: transparent;
  /*
   * The startup hamster is drawn as a background on #out, so he is sized and
   * placed against the ELEMENT's box. That was free when main filled the
   * panel; once it shrank to fit its contents (the results-box change) the
   * front door had about forty pixels of height to draw him in and he came
   * out thumbnail-sized and stranded. He needs room reserved, and only here.
   */
  min-height: min(58vh, 470px);
}

/* ---------- the loading wheel (web-loading.js) ---------- */

/*
 * taskpane.js writes its own "Loading dictionary…" line into #out, which is
 * right in Word and redundant here -- the wheel says the same thing better.
 * Hidden rather than removed, so nothing in taskpane.js has to change and the
 * line comes back the instant the body class goes away.
 */
body.rh-loading #out .status { visibility: hidden; }

#rhload {
  position: fixed;
  left: 50%;
  top: 46%;
  transform: translate(-50%, -50%);
  text-align: center;
  /* Never in the way of the search box: someone who wants to start typing
     while this is on screen must be able to click straight through it. */
  pointer-events: none;
  transition: opacity 300ms ease;
}

#rhload.rhdone { opacity: 0; }

#rhload svg {
  width: 104px;
  height: 104px;
  display: block;
  margin: 0 auto 14px;
}

#rhload .rhtrack {
  fill: none;
  stroke: var(--rule);
  stroke-width: 6;
}

/* The spokes turn from the centre; without this they orbit the corner. */
#rhload .rhspokes {
  stroke: var(--faint);
  stroke-width: 2;
  transform-origin: 45px 45px;
}

/*
 * The progress arc. Rotated so it starts at twelve o'clock instead of three,
 * and drawn in --accent (Word blue in light, a pale blue in dark) -- a hue
 * that stays legible for him in both themes. The percentage underneath is not
 * decoration: it is the unambiguous version of what the ring is showing, for
 * anyone the colour does not reach.
 */
#rhload .rhfill {
  fill: none;
  stroke: var(--accent);
  stroke-width: 6;
  stroke-linecap: round;
  transform: rotate(-90deg);
  transform-origin: 45px 45px;
}

#rhload .rhpct {
  margin: 0;
  font-size: 15px;
  font-weight: 600;
  color: var(--fg);
}

#rhload .rhline {
  margin: 4px 0 0;
  font-size: 13px;
  color: var(--muted);
}

#rhload .rhqueued {
  margin: 10px 0 0;
  font-size: 13px;
  font-style: italic;
  color: var(--accent);
  min-height: 1em;
}

@media (prefers-reduced-motion: reduce) {
  #rhload .rhspokes { transform: none !important; }
}

/* ---------- one column, one width, his ruling 2026-08-11 ---------- */

/*
 * "I *always* want the search box to STAY THE SAME SIZE AS THE FOUND WORD
 * BOX. Sometimes it stretches."
 *
 * It did, and here is why: the column was being built two different ways.
 * The box set its own width with `min(640px, 100% - 24px)`, while the header
 * got its column from PADDING inside a `min-width: 1000px` media query -- so
 * anywhere between about 664px and 1000px of window the query was off, the
 * header fell back to 12px gutters, and the search bar ran the full width of
 * the window while the box below it stayed at 640. Two mechanisms, two
 * answers, and a visible mismatch in the gap between them.
 *
 * Now there is ONE mechanism, and no media query on either: the search bar
 * and the box carry the same expression, so they cannot disagree. On a phone
 * they narrow together to the window minus a 12px gutter a side.
 *
 * The header's rule and the footer's rule still span the whole window; they
 * are the frame of the app, not part of the column.
 */
#rhbar {
  position: relative;
  width: min(640px, 100% - 24px);
  margin: 0 auto;
  /*
   * A HALO, not a dimmer banner. The wordmark art is dense right where the
   * search box sits and the box was getting lost in it -- but turning the
   * whole banner down would pay for one overlap by flattening the artwork
   * everywhere. This clears only the inch around the box.
   *
   * Two shadows doing different jobs: a tight near-solid ring that gives the
   * box a clean edge to sit against, and a wide soft one that fades the
   * banner words out gradually so there is no visible cut line.
   */
  border-radius: 6px;
  box-shadow: 0 0 0 6px rgba(255, 255, 255, .82),
              0 0 26px 14px rgba(255, 255, 255, .68);
}
@media (prefers-color-scheme: dark) {
  /* Same job, opposite ink: on dark the halo has to be the PAGE colour, or
     a white glow would light up the very words it is meant to quiet. */
  #rhbar {
    box-shadow: 0 0 0 6px rgba(31, 31, 31, .85),
                0 0 26px 14px rgba(31, 31, 31, .70);
  }
}

footer {
  padding-left: max(12px, calc((100% - 640px) / 2));
  padding-right: max(12px, calc((100% - 640px) / 2));
}

/*
 * COLUMN COUNT FOLLOWS THE COLUMN, NOT THE WINDOW. taskpane.css steps the
 * rhyme list 2 -> 3 -> 4 -> 5 -> 6 columns on media queries, which is right
 * in Word where the panel IS the window. On the web those queries saw a
 * 1440px window and packed six columns into a 640px box -- about 100px each,
 * which broke "squeeze play" across two lines.
 */
/*
 * 664px, NOT 1000. The box is `min(640px, 100% - 24px)`, so 664 is exactly
 * the window width at which it stops growing and pins at 640 -- which makes
 * it the width at which the window stops being a fair proxy for the box.
 *
 * The first version of this rule said 1000px and left a 68-pixel hole:
 * taskpane.css goes to SIX columns at 932, so between 932 and 999 the pane's
 * rule won and six columns were packed into a 640px box. That is precisely
 * the window Jeremy was sitting at when he reported it ("list view on the
 * computer version is defaulting to six columns"). Below 664 the box really
 * is the window minus 24px, and taskpane.css's own scale fits it.
 */
@media (min-width: 664px) {
  ul { columns: 4; }
}

/*
 * THE WIDTH ARROW IS CUT (his ruling, same day). Both halves went: there is
 * no button and no `rh-wide` state, so nothing here is half-wired waiting to
 * be rediscovered.
 */

/* ---------- the lime row in the footer ---------- */

/*
 * Six icons, right-justified, one per slot. margin-left:auto pushes the whole
 * row to the right of everything already in the footer, and the footer's own
 * padding is max(12px, (100% - 640px) / 2) -- the SAME inset the results box
 * uses -- so the row's right edge lands on the results box's right edge at
 * desktop width and stays aligned when the column collapses on a narrow
 * window. No second number to keep in sync.
 */
#rhlimes {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 7px;
  flex: 0 0 auto;
}
#rhlimes img {
  height: 26px;          /* the footer's content height exactly */
  width: auto;
  display: block;
  /* The art is painted, not tinted, so it cannot follow the theme. On dark it
     sits on #1f1f1f with nothing behind it; a hair of lift keeps the darker
     pieces (the pine, the sign's frame) from disappearing into the ground. */
}
@media (prefers-color-scheme: dark) {
  #rhlimes img { filter: brightness(1.08); }
}
/* The tray (Copy/Clear) appears and disappears as words are gathered. When it
   is there it must not shove the row off the end, so the row yields first. */
#tray:not([hidden]) ~ #rhlimes { min-width: 0; }


/* ---------- touch (web only) ---------- */

@media (hover: none) {
  /*
   * The bottom pane was tucking into the iPhone's rounded corners and the
   * gear was half-unreachable. env() lifts the row above the home indicator
   * (needs viewport-fit=cover on the meta, added the same day), and the
   * ::before pad grows the gear's HIT AREA -- mostly upward and outward,
   * his ask -- without moving a pixel of what is drawn.
   */
  footer { padding-bottom: calc(6px + env(safe-area-inset-bottom, 0px)); }
  #optbtn { position: relative; }
  /* Second helping 2026-08-15 -- the first grace (-10/-6/-14/-6) was still
     missable with the pane tucked into the iPhone's rounded corner. The pad
     now reaches well up and left, where the missed taps land; the right
     edge stays modest so it never steals from #blockbtn beside it. */
  #optbtn::before {
    content: "";
    position: absolute;
    left: -16px;
    right: -6px;
    top: -22px;
    bottom: -12px;
  }
}


/* Desktop keeps "+ Add rhyme" at full strength -- the quieting in
   taskpane.css is for the two narrow panes, not for here. */
@media (min-width: 768px) {
  .addopen { opacity: 1; }
}


/* The Word pane's 304px floor must not reach the website: a 390px phone with
   a forced minimum would be fine today and sidescroll the day the floor
   grows. The web's layouts manage their own widths. */
html, body { min-width: 0; }


/*
 * THE PANE WORDMARK IS WORD-ONLY. taskpane.html grew a centred #panemark
 * above the search bar on 2026-08-16 (his experiment). The website already
 * builds its own wordmark -- web-layout.js mounts #rhmark on the scrolling
 * band -- so showing this one as well would put TWO wordmarks on one screen,
 * which his 2026-08-11 note about the band explicitly warned against.
 *
 * display:none rather than a width tweak: it must leave the layout entirely,
 * or its margin would still open a gap above the search bar here.
 */
#panemark { display: none; }


/* ---------- the website's startup watermark ---------- */

/*
 * A second `#out.startup::before/::after { opacity: 0.46 }` lived here from
 * 2026-08-15 until 2026-08-16, and it was a REGRESSION, not a ruling. It was
 * written to "restore the watermark weight on the website" without noticing
 * that the top of this very file already carries his 2026-08-11 ruling --
 * "get rid of all transparency for the hamster and the wordmark on the
 * website" -- implemented as `opacity: 1`. Same selector, same specificity,
 * 800 lines later, so it silently won and the front door went faint. He
 * caught it: "the hamster and wordmark are no longer 100% opacity! what
 * happened? I want it to be 100%."
 *
 * The rule is deleted rather than corrected: the opacity:1 block near the top
 * is the one that states the intent, and two blocks setting one property on
 * one selector is how this happened in the first place. If the website's
 * watermark weight ever needs to change again, change it THERE.
 */


/* ---------- phone portrait: the front door, his rulings 2026-08-16 -------- */

@media (max-width: 479px) {
  /*
   * "On mobile, I want the hamster at 100% capacity." He already IS at
   * opacity 1 from the rule at the top of this file, and nothing in the phone
   * blocks was dimming him -- this restates it INSIDE the phone block so a
   * future mobile tweak cannot quietly take it back. The watermark era is
   * over on every surface; read the note above before changing it.
   */
  #out.startup::before { opacity: 1; }

  /*
   * "Scooch the words 'RhymeHamster is fed…' up and move the hamster down a
   * bit." Two halves of one gap, moved in opposite directions: the greeting
   * loses its top margin and rides up under the search bar, and the hamster's
   * top edge drops from 15% to 26%.
   *
   * The hamster is a background on a PSEUDO-ELEMENT whose box is #out, so
   * moving him is a matter of that box's top inset, not a margin. His BOTTOM
   * edge is deliberately left alone: it is derived from the wordmark's band
   * in taskpane.css, and moving it is what once put the wordmark on his feet.
   */
  #out .status { margin-top: 0; }
  #out.startup::before { top: 26%; }
}


/* ---------- beta telemetry: the consent dialog and its settings row ------- */

/*
 * Website-only chrome for web-telemetry.js, 2026-08-18. The Word pane never
 * shows either of these -- it doesn't load the script that builds them.
 *
 * The dialog is a real modal, unlike the pane's #confirm bar: it asks a
 * question about the visitor's data, and a question like that should hold
 * still and be answered, not sit in the footer competing with the Copy tray.
 * Clicking the dark backdrop counts as "No thanks" (web-telemetry.js wires
 * it so), which is why the backdrop is clickable at all.
 */
#telask {
  position: fixed;
  inset: 0;
  z-index: 60;                    /* above #options (20) and the popovers */
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 18px;
  background: rgba(0, 0, 0, .35);
}
#telask .telcard {
  max-width: 380px;
  padding: 16px 18px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--fg);
  background: var(--bg);
  border: 1px solid var(--rule);
  border-radius: 8px;
  box-shadow: 0 6px 22px rgba(0, 0, 0, .25);
}
#telask .telcard p { margin: 0 0 12px; }
#telask .telrow {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
}
#telask button {
  font: inherit;
  padding: 6px 14px;
  border-radius: 5px;
  cursor: pointer;
}
/* "Allow" carries the accent -- it is the action the dialog exists to offer.
   "No thanks" is a plain quiet button, visible but never nagging. */
#telyes {
  color: #fff;
  background: var(--accent);
  border: 1px solid var(--accent);
}
#telno {
  color: var(--fg);
  background: var(--field);
  border: 1px solid var(--rule);
}

/* "Other settings", his ruling 2026-08-18: the share checkbox lives in a
   disclosure like the two groups above it, not as a bare appendix row. These
   rules MIRROR taskpane.css's #familygroup/#loosegroup styling -- that file
   cannot name #othergroup because the element only exists on the website
   (web-telemetry.js builds it). If the group styling ever changes there,
   change it here too. */
#othergroup {
  margin-top: 11px;
  padding-top: 8px;
  border-top: 1px solid var(--rule);
}
#othergroup > summary > span { padding-left: 6px; }
#othergroup > summary {
  cursor: pointer;
  user-select: none;
  opacity: .45;
  font-size: 11px;
  letter-spacing: .02em;
  padding: 1px 0;
}
#othergroup > summary:hover { opacity: 1; color: var(--accent); }
#othergroup[open] > summary { margin-bottom: 3px; }


/* ---------- desktop front door: the hamster, his rulings 2026-08-18 ------- */

/*
 * Three rulings, one block, desktop only (the phone block above keeps its own
 * 2026-08-16 rulings; the min-width scope is what stops the two fighting).
 *
 *   "lower the hamster some more"
 *   "make the hamster a tad bigger"
 *   "scooch the hamster down so his ears are BELOW where it says
 *    'XXXXX words, offline.'"
 *
 * EARS BELOW THE COUNT LINE, guaranteed by the BOX, not by arithmetic on the
 * image: contain cannot draw outside the box, so pinning the box's top edge
 * under the status block means no size of hamster can ever poke above it.
 * The 124px is measured: the greeting + count block ends ~104px into #out at
 * a wide window and a little deeper when the greeting wraps; 124 clears it
 * with room at every desktop width tried. A percentage top would NOT hold --
 * it scales with the box while the text does not.
 *
 * LOWER: bottom drops to 0 -- he stands on the floor of the box. The old
 * calc(18% + 44px) was the wordmark band plus a gap, both gone from under
 * him since the lockup was cut earlier today.
 *
 * BIGGER: the box is taller (min-height 58vh->66vh, cap 470->520), and with
 * top and bottom both pinned the freed height goes straight into him. His
 * HEIGHT is the binding edge here (the art is 384x600, taller than wide), so
 * the width cap of 265px is headroom rather than the working number.
 */
@media (min-width: 480px) {
  main.startup { min-height: min(66vh, 520px); }
  #out.startup::before {
    top: 124px;
    bottom: 0;
    width: min(76%, 265px);
  }
}
