/* ═══════════════════════════════════════════════════════════════════════════
   UI v2 — item detail

   Full-bleed photo, then a white sheet with one primary action. All colour
   comes from the tokens in style.css.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Fixed full-height screen: the hero flexes, the sheet takes what it needs,
   and nothing scrolls. */
.detail-page {
  flex: 1;
  min-height: 0;
  overflow: hidden;
  background: var(--surface);
  display: flex;
  flex-direction: column;
}

/* The photo swipes to the item beside it (2026-09-21). A scroll-snapping strip
   rather than a touch handler, as the Home rails are: the gesture, its momentum
   and the page's own scrolling stay the phone's. It was three panels recentred
   on the middle until 2026-09-23; it is now a deep window that grows at its far
   end, and why is at the top of itemDetail.js.

   The scrollbar is hidden rather than styled: on a phone there is none, and on
   a desktop one across the photo would be the only one in the app. */
/* The strip's slot in the column, and the thing the fade is drawn on. It does
   not scroll, which is the whole point of it (2026-09-22). */
.detail-strip-wrap {
  flex: 1 1 auto;
  min-height: 120px;
  min-width: 0;
  display: flex;
  position: relative;
}

.detail-strip {
  /* One height, whatever the words below say (2026-09-21). It used to flex, so
     every extra line of name or category was taken out of the picture — which
     nobody noticed while the screen showed one item, and which jerked under the
     thumb once the photo became something you swipe. Measured across every
     item at 390×844: three photo heights, 352/359/378, and three button
     positions with them.

     The photo still takes whatever the sheet leaves — but the sheet is now the
     same height for every item (see .detail-title and .detail-category), so
     what it leaves is the same too. A fixed share of the screen was tried
     first and could not know how much room two lines of text need at a given
     width: it held at 390x844 and let the button move 26px at 375x667. */
  flex: 1 1 auto;
  min-height: 120px;
  display: flex;
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  overscroll-behavior-x: contain;
  /* An opaque ground under the photos (2026-09-23). Nothing shows it while the
     panels are painted; it is there for the frame where one is not, so that
     what appears is the page's own cream rather than the web view's white
     (capacitor.config.json sets #FFFFFF behind the page on both platforms).
     It was added while chasing that white and did not fix it — the recentre in
     itemDetail.js did — and is kept because a scroller full of photographs
     should not be see-through onto the native view whatever happens. */
  background: var(--surface);
}

/* `-webkit-overflow-scrolling: touch` was removed from the rule above on
   2026-09-23, and from the other four stylesheets that carried it the same day.
   It was suspected of the white band and was not the cause — the strip's own
   recentre was, and removing that is what fixed it. It goes anyway, everywhere:
   momentum has been the default since iOS 13, the property was dropped from
   Safari at the same time, and capacitor_ios builds for 15.0 and up, so it does
   nothing on any phone the app runs on. tests/js/legacyScrolling.test.js keeps
   it out. */
.detail-strip::-webkit-scrollbar { display: none; }

.detail-panel {
  flex: 0 0 100%;
  scroll-snap-align: center;
  scroll-snap-stop: always;
  display: flex;
  min-width: 0;
}

.detail-panel > .detail-hero {
  flex: 1 1 auto;
  width: 100%;
}

/* The same cue the Home rails use for "there is more sideways" (2026-09-19),
   and only when there is: an item with nothing beside it does not fade.

   Drawn over the photo rather than masked out of it (2026-09-22). A mask forces
   the scroller into a layer of its own and, on iOS, is painted against the
   scrolled content — so each time drawStrip() jumped the scroll back to the
   middle the see-through band went with it and showed white (the web view's own
   background, capacitor.config.json) down the left edge until the layer
   repainted. The rails never move their own scroll position, which is why they
   have the same mask and do not flicker.

   The gradient ends on --surface because that is what the mask used to reveal:
   the strip's parent is the page. Both stops are the same colour — a gradient
   to `transparent` is a gradient to transparent *black*, and greys on the way. */
.detail-strip-wrap--more::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 44px;
  pointer-events: none;
  background: linear-gradient(to right, rgba(244, 233, 216, 0), var(--surface));
}

.detail-hero {
  flex: 1 1 auto;
  min-height: 120px;
  background: var(--surface-sunken);
  overflow: hidden;
  /* Flagged: added 2026-09-16 so the heart below can sit in its corner. Nothing
     else in here is positioned, so this changes nothing on its own. */
  position: relative;
}

/* Bottom right of the photo. A plain heart with a shadow so it still reads on
   a pale picture. It first sat on a white disc, dropped 2026-09-16 when Hugh
   asked for no circle. At the row heart's 18px it was too small, too high and
   too far right (Hugh, 2026-09-16), so now 26px — its own value, as the tokens
   jump from 22 to 32 — about 11px above the white panel and 29px in from the
   edge. The offsets allow for .detail-sheet's -22px margin, which covers the
   bottom of the photo, and for the 48px tap area around the heart. Colours and
   the rest are .heart-btn in items.css.
   Both classes in the selector: base.html loads items.css after this file, so
   .heart-btn's own font-size and padding won on a tie and the heart stayed
   18px whatever was set here. */
.heart-btn.detail-hero-heart {
  position: absolute;
  right: 18px;
  bottom: 22px;
  width: 48px;
  height: 48px;
  font-size: 26px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 0;
  text-shadow: 0 0 1px rgba(12, 29, 54, .6), 0 1px 4px rgba(12, 29, 54, .5);
}

/* White on the photo, not the row's grey, which was lost on a picture (Hugh,
   2026-09-16). Hearted stays green. The shadow above keeps white visible on a
   white photo or the pale no-photo ground: the soft one alone left only a
   halo on white, so a tight one draws the edge. */
.detail-hero-heart:not(.heart-btn--on) {
  color: var(--text-on-brand);
}

.detail-hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.detail-hero--tappable { cursor: pointer; }

/* no photo: the tier-1 category icon, centred */
.detail-hero.thumb--icon {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Flagged: was `i`, 2026-09-16. The heart in the corner is an <i> too, and
   was drawn at 84px; only the category icon is a direct child. */
.detail-hero.thumb--icon > i {
  font-size: 84px;
  opacity: .38;
}

.detail-sheet {
  /* A frame of a fixed size that the words sit inside, rather than a box that
     grows to fit them: that is what keeps the photo and the button still.
     .detail-cta's margin-top: auto then holds the button at the bottom of it. */
  flex: 0 0 auto;
  margin-top: -22px;
  /* Nothing inside shrinks — see .detail-sheet > * below. Flex items shrink by
     default, so the fixed frame squashed the longest name's title into 41px of
     the 54 it needed and cut it through the middle. */
  /* Flagged: 22px → 34px above the title, 2026-09-17 (Hugh chose it from
     other stuff/item-title-space-options.png).

     The sides are the app's own margin since 2026-09-23 (Hugh: "make same uni
     margin as messages, home etc"). They were 20px, a number of this file's
     own, which put both item screens 5px further in than Home, Messages and
     Borrow. Everything on the sheet measures from here, so this one line moves
     the title, the category, the card, the band, the buttons and the hint.
     The vertical values are deliberately untouched: the sheet's *height* is
     what holds the photo at the size the two screens agreed on. */
  padding: 34px var(--uni_margin) 32px;
  background: var(--surface-raised);
  border-radius: 24px 24px 0 0;
  display: flex;
  flex-direction: column;
}

/* Which stretch of the swipe you are in (2026-09-25), above the title.
   An overline: small, quiet, and the same words the list it came from carries
   in its own heading — "Free to keep", then "More to borrow".

   It only exists when the screen was opened from a list, so it is the one thing
   on the sheet that can be absent. That costs the photo 22px when it is there
   and gives them back when it is not, which is a difference between two
   openings rather than between two items in one swipe — the height still
   cannot change under the thumb, which is the rule this sheet is built around.

   Nothing in the strip marks the seam: panel width, gaps and snap points are
   what three iOS builds went into (see the note at the top of this file). */
.detail-stretch {
  font-size: var(--text-xs);
  font-weight: var(--weight-heavy);
  letter-spacing: .5px;
  text-transform: uppercase;
  color: var(--text-muted);
  line-height: 1.4;
  height: 16px;
  margin-bottom: 6px;
  overflow: hidden;
}

.detail-stretch[hidden] { display: none; }

/* The change is the thing worth marking, so the emphasis fires on a crossing
   and never on an ordinary swipe (itemStretch.js decides which). It rises and
   darkens once: enough to catch the eye that has just moved a photograph,
   short enough not to still be happening when the next swipe starts. */
.detail-stretch--changed {
  animation: stretch-changed .42s ease-out;
}

@keyframes stretch-changed {
  from { opacity: 0; transform: translateY(4px); color: var(--text-primary); }
  60%  { opacity: 1; transform: translateY(0);   color: var(--text-primary); }
  to   { opacity: 1; transform: translateY(0);   color: var(--text-muted); }
}

@media (prefers-reduced-motion: reduce) {
  /* The words still change; only the movement goes. */
  .detail-stretch--changed { animation: none; }
}

.detail-title {
  margin: 0;
  font-size: var(--text-2xl);
  font-weight: var(--weight-heavy);
  letter-spacing: -.3px;
  color: var(--text-primary);
  /* Always two lines' worth, whether the name needs them or not (2026-09-21).
     That is what stops the screen jerking as you swipe: the words are the only
     thing that varies between items, so the space they are given cannot.
     A short name leaves the second line empty, which reads as spacing; a long
     one is cut off at two, because a name is free text and an unbounded one
     would push the Ask button off the bottom.

     A height rather than -webkit-line-clamp, which makes this a -webkit-box —
     and a free item's title has a gift icon in it, which the box counts as one
     of its two lines and cuts the name in half.

     The line-height is 1.3, not 1.2, and the height is two of those: at 1.2 the
     box was exactly two line boxes, and a descender hangs below its own line —
     so "Silicone cups for measuring resin / epoxy" had the tails of its p and y
     shaved off (Hugh, 2026-09-21). The rule is that the reserved height has to
     be the line-height it is reserving, with room for what hangs below. */
  line-height: 1.3;
  /* The 2px is the rounding: two lines of 28.6 is 57.2, which lays out as a
     57px box holding 58px of text, and that last pixel is the tail of a y. */
  height: calc(2.6em + 2px);
  overflow: hidden;
}

/* Two lines' worth, always, for the same reason as the title. Two is what the
   longest paths take — "Home & Kitchen › Kitchen Appliances › Small Kitchen
   Appliances" — so the full path is kept on the one screen with room for it. */
.detail-category {
  margin-top: 6px;
  font-size: var(--text-sm);
  color: var(--text-secondary);
  /* 1.55 and two of them, for the descenders — the "g" of "Printing" on a
     second line was being shaved the same way. */
  line-height: 1.55;
  height: calc(3.1em + 2px);
  overflow: hidden;
}

.detail-state {
  align-self: flex-start;
  margin-top: 12px;
}

.detail-owner {
  display: flex;
  align-items: center;
  gap: 11px;
  margin-top: 18px;
  padding: 12px;
  background: var(--surface);
  border-radius: 14px;
  /* Tall enough for a name and two lines of address, whoever it is (2026-09-21).
     The card keeps its height rather than the address keeping its space, so
     somebody with no address has their name centred instead of floating above a
     gap — and the screen still cannot change height between items. */
  height: 86px;
  overflow: hidden;
}

.detail-avatar {
  width: 42px;
  height: 42px;
  /* An <img> since 2026-09-21, where it was a div with a letter in it. */
  object-fit: cover;
  flex: none;
  border-radius: 50%;
  background: var(--brand-navy);
  color: var(--text-on-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: var(--text-md);
  font-weight: var(--weight-heavy);
}

.detail-owner-mid { flex: 1; min-width: 0; }

/* The handle is one line and gives way with an ellipsis; min-width: 0 above is
   what lets a flex child shrink far enough to do that at all. */
.detail-owner-name {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.detail-owner-name {
  font-size: var(--text-sm);
  font-weight: var(--weight-heavy);
  color: var(--text-primary);
}

/* Addresses are free text and run from "Catford" to "Flat 6 Dartmouth House
   SE10 8BF", so this takes one line or two. The room for the second is reserved
   on the card itself, not here: reserving it here left a hole under the name of
   anybody without an address, and the card is what has to keep its height. */
.detail-owner-loc {
  font-size: var(--text-xs);
  color: var(--text-secondary);
  margin-top: 2px;
  line-height: 1.5;
}

/* On the photo, top left — the corner opposite the heart (2026-09-21). It sat
   beside the owner's face for an afternoon, which put a fact about the item
   inside a card about a person: "Out on loan" next to somebody's photograph.

   A photo is anything — a white sink, a dark shed — so the pill carries the
   same kind of shadow the heart does, and a hairline of its own colour, rather
   than trusting a pale tint to hold on its own. */
.detail-hero > .detail-state {
  position: absolute;
  top: 16px;
  left: 16px;
  margin: 0;
  z-index: 1;
  box-shadow: 0 1px 6px rgba(12, 29, 54, .28),
              inset 0 0 0 1px color-mix(in srgb, currentColor 20%, transparent);
}

/* the single action, pinned to the bottom of the sheet */
/* 26px → 14px, and the sheet's bottom padding 20px → 32px, on 2026-09-23. The
   + on the bar overhangs the sheet by enough to run 4px into the hint, and the
   sheet's bottom edge is pinned to the bar — so the only way to lift the last
   line is its bottom padding, which would otherwise make the sheet taller and
   the photo shorter. Moving the same 12px from above the button to below the
   hint lifts the words clear and leaves the sheet, and the photo, exactly as
   they were. */
.detail-cta {
  margin-top: auto;
  padding-top: 14px;
}

.detail-btn {
  width: 100%;
  padding: 17px;
  border: none;
  border-radius: 15px;
  font: inherit;
  font-size: var(--text-base);
  font-weight: var(--weight-heavy);
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
  transition: transform 120ms ease-out;
}

.detail-btn:active { transform: scale(.98); }

.detail-btn--primary {
  background: var(--action-borrow);
  color: var(--text-on-brand);
  box-shadow: var(--shadow-borrow);
}

/* Says what the button will actually do, so asking doesn't feel like a
   commitment the user can't see the shape of.

*/
.detail-hint {
  margin-top: 9px;
  text-align: center;
  font-size: var(--text-xs);
  color: var(--text-secondary);
}

/* ═══════════════════════════════════════════════════════════════════════════
   Your own item — the same screen in orange (2026-09-23, itemEdit.js)

   Hugh: "should be similar to the view item modal but orange not green ...
   keep image the same size as it is for browsing items you want to borrow."

   The photo is whatever the sheet leaves, so the two sheets are built from the
   same four boxes and the photo comes out the same height with nothing
   measured: the title block (2.6em + 2px), the category block (3.1em + 2px),
   a band of 86px where the owner card sits on the other screen, and a
   .detail-cta footer holding a button and a hint. Anything added here has to
   keep that sum, or the picture changes size between the two screens.

   Orange is --action-lend, which the app already pairs with --action-borrow:
   green is for asking for somebody else's thing, orange for offering your own.
   ═══════════════════════════════════════════════════════════════════════════ */

/* The name, in the heading's own box — .detail-title is on the wrap, so the
   height and the type are the heading's and cannot drift from them.

   The wrap exists because a field cannot hold an icon: the gift mark that
   setItemTitle() puts in front of a heading on the other screen sits in here
   instead, and the text is indented past it (2026-09-23). */
.detail-title-wrap {
  position: relative;
  box-sizing: border-box;
  /* No inset of its own (2026-09-23). It used to be pulled out by 10px and
     padded back by 10, which landed the words on the sheet's margin but ran the
     tint 10px past it — two left edges on one screen. Now the box and the words
     start together, on the margin, where the other screen's heading starts.

     No fill either (Hugh, 2026-09-23: "don't have colour background for text
     elements in the lending items"). The name is words on the sheet, as it is
     on the borrow screen; the box is still here for the focus ring, which is
     the one moment a field wants an edge. The radius is the ring's shape. */
  border-radius: 12px;
}

.detail-title-wrap > .gift-icon {
  position: absolute;
  left: 0;
  /* On the first line's own centre, whatever the box's height: the mark belongs
     beside the first words, not beside the middle of two lines. */
  top: .65em;
  transform: translateY(-50%);
  display: none;
}

.detail-title-wrap--gift > .gift-icon { display: block; }

.detail-title-input {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  display: block;
  padding: 0;
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  resize: none;
  /* Two lines, and no more: a box that grew with the words would push the photo
     about under the thumb, and the photo is the same height as the borrow
     screen's only because this sheet's height cannot change. */
  overflow-y: auto;
}

/* Where the gift mark stands, on the first line only — the same place the
   other screen's heading gives it. */
.detail-title-wrap--gift > .detail-title-input { text-indent: 26px; }

.detail-title-input:focus {
  outline: none;
}

.detail-title-wrap:focus-within {
  outline: 2px solid var(--action-lend);
  outline-offset: -2px;
}

/* Where the other screen prints the category path, this one offers it. Same
   box, same height — a button rather than a line of text. */
.detail-category-edit {
  width: 100%;
  box-sizing: border-box;
  padding: 0;
  border: none;
  border-radius: 12px;
  /* No fill, for the same reason as the name above: a line of words with a
     pencil beside it, not a panel. */
  background: none;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  text-align: left;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}

.detail-category-edit > span {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The pencil is what says this row opens something, so it carries the mark of a
   control rather than the row doing (2026-09-23). The row itself stays a line
   of words on the margin: an outline around the whole row would need padding
   inside it, and that padding would push the category's words off the 15px
   every other line on the sheet starts at — the misalignment this same goal is
   fixing. Same inset outline as Delete, in the same lending orange. */
.detail-category-edit > i {
  flex: none;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  box-shadow: inset 0 0 0 1.5px var(--action-lend);
  color: var(--action-lend);
  font-size: var(--text-sm);
}

/* The 86px the owner card takes on the other screen, holding the two states
   instead. It keeps that height whatever is in it — including the line that
   replaces the switch while the item is out on loan, which the old sheet hid
   and a page cannot, or the photo above would move. */
.detail-controls {
  flex: 0 0 auto;
  margin-top: 18px;
  height: 86px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.detail-control-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.detail-control-label {
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  color: var(--text-primary);
}

.detail-control-note {
  font-size: var(--text-sm);
  color: var(--text-secondary);
}

/* On is the lending colour here, not the app's usual navy: this switch is the
   one that says whether you are offering the thing. */
.detail-controls .switch { margin-left: 0; }
.detail-controls .switch input:checked + .slider { background-color: var(--action-lend); }

/* The two halves are the control, so they are what lands on the margin
   (2026-09-23). The track used to hold 3px of padding, which put the coloured
   half you actually look at at 18px while the name, the category, Delete and
   the hint all started at 15 — the one thing on the sheet out of line. The
   track's tint showed only as that 3px rim, so it goes with the padding and
   each half carries its own ground. */
.detail-seg {
  padding: 0;
  gap: 3px;
  background: none;
}

/* .toggle-half in style.css sets background-color and color with !important,
   so the active half can only be coloured with !important of its own. */
.detail-seg .toggle-half {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px 2px;
  border: none !important;
  border-radius: 11px;
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  background-color: var(--surface-sunken) !important;
  color: var(--text-secondary) !important;
  box-shadow: none;
}

.detail-seg .toggle-half.active-toggle {
  background-color: var(--action-lend) !important;
  color: var(--text-on-brand) !important;
}

/* Deliberately not a filled button. It stands where "Ask to borrow" stands on
   the other screen, and a thumb that has learnt that spot must not delete
   something with it — the outline says "not the thing you came to press", and
   the confirmation behind it is the sheet's own.

   The outline is an inset shadow rather than a border because a border is 3px
   of height that the other screen's button does not have: measured at 390×844,
   it made this sheet 377px against 375px and took two pixels off the photo,
   which is exactly what Hugh asked to keep the same. */
.detail-btn--delete {
  background: transparent;
  color: var(--action-lend);
  box-shadow: inset 0 0 0 1.5px var(--action-lend);
}

/* Who has it, when one of your things is out on loan (2026-09-23). The borrow
   screen's owner card, at the borrow screen's height — which is the band's
   height, so the sheet is the same size whether the item is out or not. */
.detail-owner--holder { margin-top: 0; }

.detail-owner--tappable { cursor: pointer; }

/* Nobody to draw: a person shape rather than an initial that would belong to
   the wrong person. The disc, its size and its colour are .detail-avatar's. */
.detail-avatar--nobody > i {
  font-size: var(--text-md);
  opacity: .8;
}

/* The way out, for an item held by somebody who cannot be reached. Quiet, and
   the same outline as Delete: it is a correction, not the thing you came to
   press. */
.detail-return-btn {
  flex: none;
  padding: 9px 12px;
  border: none;
  border-radius: 11px;
  background: transparent;
  box-shadow: inset 0 0 0 1.5px var(--action-lend);
  color: var(--action-lend);
  font-family: inherit;
  font-size: var(--text-sm);
  font-weight: var(--weight-bold);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
