/* ==========================================================================
   KH Haircare — review page
   Loaded only by review.html, after layout.css. Nothing in here is used by
   any other page, which is why it is a separate sheet.

   Page heading · reviews list and cards · form fields · star rating control ·
   photo picker · success panel
   ========================================================================== */


/* ==========================================================================
   PAGE HEADING
   No hero here, so the first section clears the fixed header itself — the
   same arrangement as .about-intro, and the same two-line treatment with the
   second word carrying the accent.
   ========================================================================== */

.review-intro{
  padding-block:calc(var(--header-h) + clamp(2rem,5vw,3.5rem)) clamp(1.5rem,4vw,2.5rem);
}

/* Below the hero's --step-3, matching .about-intro__name: this is a page
   heading, not a headline. */
.review-intro__title{
  font-size:var(--step-2);
}


/* ==========================================================================
   REVIEWS LIST
   Cream cards on the blush band, separated by hairlines. No drop shadows —
   a card should read as a panel of the page, not a tile floating over it.
   Built by assets/js/reviews.js.
   ========================================================================== */

.review-list{
  padding-block:clamp(1.5rem,4vw,2.5rem) clamp(3rem,7vw,5rem);
  background:var(--kh-blush);
}

/* The grid and the empty line both start with the hidden attribute, and
   reviews.js drops it from whichever one applies and adds .is-ready on the
   next frame so it settles in rather than snaps. No `display` is set on the
   grid here — it comes from the rule below, which the hidden attribute
   outranks through base.css. */
.review-list__grid,
.review-list__empty{
  opacity:0;
  transition:opacity .6s var(--ease);
}

.review-list__grid.is-ready,
.review-list__empty.is-ready{
  opacity:1;
}

.review-list__grid{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(1rem,2.4vw,1.5rem);
  align-items:start;
}

/* The whole of the empty and error states. Deliberately one quiet line and
   nothing else — no illustration, no box, no apology. */
.review-list__empty{
  font-size:var(--step-0);
  color:var(--kh-muted);
}

/* --- Card ----------------------------------------------------------------- */

.review-card{
  display:flex;
  flex-direction:column;
  gap:.85rem;
  /* min-inline-size:0 on the grid track handles the column, this handles the
     content: a pasted URL or a long unbroken name would otherwise push the
     card wider than its track and take the page into horizontal scroll. */
  min-inline-size:0;
  padding:clamp(1.25rem,3vw,1.75rem);
  background:var(--kh-cream);
  border:1px solid var(--kh-hairline);
  border-radius:var(--radius);
}

/* Deliberately the body face, not the display one: a visitor may write her
   name in Arabic script while the site is in English, and Playfair has no
   Arabic glyphs to render it with. */
.review-card__name{
  font-size:var(--step-0);
  font-weight:500;
  line-height:1.3;
  color:var(--kh-ink);
  overflow-wrap:anywhere;
}

.review-card__text{
  color:var(--kh-muted);
  overflow-wrap:anywhere;
}

/* --- Stars ---------------------------------------------------------------- */

/* No direction handling needed: as flex items the stars lay out along the
   writing direction, so Arabic fills from the right on its own. */
.stars{
  display:flex;
  gap:.2rem;
}

.stars .star{
  inline-size:var(--star);
  block-size:var(--star);
  fill:var(--kh-copper);
  opacity:.25;
}

.stars .star.is-on{
  opacity:1;
}

/* --- Photos --------------------------------------------------------------- */

/* Flex rather than grid so the row mirrors under RTL for free. */
.review-card__photos{
  display:flex;
  gap:.5rem;
  margin-block-start:.15rem;
}

.review-card__photos img{
  inline-size:100%;
  block-size:auto;
  object-fit:cover;
  border-radius:var(--radius-sm);
}

.review-card__photos--single img{
  aspect-ratio:4 / 5;
}

/* Equal widths whatever the photos' own proportions, so two and three both
   read as one band across the card. */
.review-card__photos--row img{
  flex:1 1 0;
  min-inline-size:0;
  aspect-ratio:1 / 1;
}


/* ==========================================================================
   WRITE
   ========================================================================== */

.review-write{
  padding-block:clamp(3rem,7vw,5rem);
}

.review-write__title{
  margin-block-end:clamp(1.5rem,4vw,2.25rem);
  font-size:var(--step-2);
}


/* ==========================================================================
   FORM
   One column on phones, two once there is room for the name fields to sit
   side by side. Everything else spans.
   ========================================================================== */

.review-form{
  display:grid;
  gap:1.5rem;
  max-inline-size:var(--field);
}

.field{
  /* Fieldsets carry an intrinsic minimum width that ignores the grid track,
     which is exactly how a form starts overflowing at 360px. */
  min-inline-size:0;
  border:0;
  padding:0;
}

.field__label{
  display:block;
  margin-block-end:.5rem;
  padding:0;                     /* legend */
  font-size:var(--step--1);
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--kh-muted);
}

.field__hint{
  margin-block:-.2rem .6rem;
  font-size:var(--step--1);
  color:var(--kh-muted);
}

.field__control{
  inline-size:100%;
  padding:.8em 1em;
  background:var(--kh-ivory);
  border:1px solid var(--kh-line);
  border-radius:var(--radius-sm);
  color:var(--kh-ink);
  transition:border-color .35s var(--ease);
}

.field__control::placeholder{
  color:var(--kh-muted);
}

.field__control:hover{
  border-color:var(--kh-hairline);
}

.field__control--area{
  resize:vertical;
  min-block-size:9rem;
  line-height:1.7;
}

/* --- Counter -------------------------------------------------------------- */

.field__counter{
  margin-block-start:.4rem;
  font-size:var(--step--1);
  color:var(--kh-muted);
  text-align:end;
  font-variant-numeric:tabular-nums;
  transition:color .35s var(--ease);
}

.field__counter.is-near-limit{
  color:var(--kh-copper);
}

/* --- Errors --------------------------------------------------------------- */

/* Never display:none. These are aria-live regions, and a region that is not
   in the accessibility tree at the moment its text changes is not announced.
   An empty <p> generates no line box, so it costs nothing while it is silent
   — only the margin is held back until there is something to separate. */
.field__error,
.review-form__status{
  font-size:var(--step--1);
  color:var(--kh-copper-deep);
}

.field__error:not(:empty){
  margin-block-start:.5rem;
}

.review-form__status:not(:empty){
  padding:.8em 1em;
  background:var(--kh-sand);
  border-radius:var(--radius-sm);
}

.field.has-error .field__control{
  border-color:var(--kh-copper-deep);
}


/* ==========================================================================
   RATING
   Five real radios with the stars drawn over them. Nothing here depends on a
   click handler: the inputs carry the state, the CSS reads it, and arrow-key
   navigation is the browser's own.
   ========================================================================== */

.rating{
  display:flex;
  gap:.35rem;
}

.rating__star{
  display:inline-flex;
  padding:.2rem;
  border-radius:var(--radius-sm);
  cursor:pointer;
}

.rating .star{
  inline-size:var(--star-input);
  block-size:var(--star-input);
  fill:var(--kh-copper);
  opacity:.25;
  transition:opacity .25s var(--ease);
}

/* The focus ring belongs on the star, since the input it describes is
   off-screen. */
.rating__input:focus-visible + .rating__star{
  outline:2px solid var(--kh-copper-deep);
  outline-offset:2px;
}

/* Fill every star up to the checked one. In Arabic the row is laid out from
   the right by flexbox, so the same rules fill it from the right. */
.rating:has(.rating__input[value="1"]:checked) .rating__star:nth-of-type(-n+1) .star,
.rating:has(.rating__input[value="2"]:checked) .rating__star:nth-of-type(-n+2) .star,
.rating:has(.rating__input[value="3"]:checked) .rating__star:nth-of-type(-n+3) .star,
.rating:has(.rating__input[value="4"]:checked) .rating__star:nth-of-type(-n+4) .star,
.rating:has(.rating__input[value="5"]:checked) .rating__star:nth-of-type(-n+5) .star{
  opacity:1;
}

/* Hover preview. Each pair lights the stars up to the hovered one and dims the
   rest, rather than relying on a separate reset rule — written this way both
   halves tie with the :checked rules above on specificity and win on source
   order, so hovering 2 with 5 already chosen previews 2, not 5.
   Pointer devices only: on touch, :hover sticks after the tap. */
@media (hover:hover){
  .rating:has(.rating__star:nth-of-type(1):hover) .rating__star:nth-of-type(-n+1) .star,
  .rating:has(.rating__star:nth-of-type(2):hover) .rating__star:nth-of-type(-n+2) .star,
  .rating:has(.rating__star:nth-of-type(3):hover) .rating__star:nth-of-type(-n+3) .star,
  .rating:has(.rating__star:nth-of-type(4):hover) .rating__star:nth-of-type(-n+4) .star,
  .rating:has(.rating__star:nth-of-type(5):hover) .rating__star:nth-of-type(-n+5) .star{
    opacity:1;
  }

  .rating:has(.rating__star:nth-of-type(1):hover) .rating__star:nth-of-type(n+2) .star,
  .rating:has(.rating__star:nth-of-type(2):hover) .rating__star:nth-of-type(n+3) .star,
  .rating:has(.rating__star:nth-of-type(3):hover) .rating__star:nth-of-type(n+4) .star,
  .rating:has(.rating__star:nth-of-type(4):hover) .rating__star:nth-of-type(n+5) .star{
    opacity:.25;
  }
}


/* ==========================================================================
   PHOTOS
   ========================================================================== */

/* .btn sets display:inline-flex, which would outrank the UA rule for the
   hidden attribute — base.css settles that with !important, and this is the
   element that needs it: the control disappears at three photos. */
.photos__add{
  padding:.75em 1.6em;
}

/* The file input is .sr-only and still the focusable control, so the ring it
   would have drawn is moved onto the label the visitor can actually see. */
.photos__input:focus-visible + .photos__add{
  outline:2px solid var(--kh-copper-deep);
  outline-offset:2px;
}

.photos__list{
  display:flex;
  flex-wrap:wrap;
  gap:.75rem;
  list-style:none;
}

.photos__list:not(:empty){
  margin-block-start:1rem;
}

.photos__item{
  position:relative;
  inline-size:var(--thumb);
  block-size:var(--thumb);
}

.photos__item img{
  inline-size:100%;
  block-size:100%;
  object-fit:cover;
  border-radius:var(--radius-sm);
}

.photos__remove{
  position:absolute;
  inset-block-start:-.5rem;
  inset-inline-end:-.5rem;
  display:grid;
  place-items:center;
  inline-size:26px;
  block-size:26px;
  padding:0;
  background:var(--kh-espresso);
  color:var(--kh-cream);
  border:0;
  border-radius:var(--radius-pill);
  cursor:pointer;
  transition:background-color .35s var(--ease);
}

.photos__remove:hover{
  background:var(--kh-copper-deep);
}

.photos__remove svg{
  inline-size:12px;
  block-size:12px;
}


/* ==========================================================================
   SUBMIT
   ========================================================================== */

.review-form__submit{
  justify-self:start;
}

.review-form__submit[disabled]{
  opacity:.6;
  cursor:progress;
}

.review-form__submit[disabled]:hover{
  background:var(--kh-espresso);
  transform:none;
}


/* ==========================================================================
   SUCCESS
   Replaces the form in place — no reload, no mention of moderation.
   ========================================================================== */

.review-success{
  max-inline-size:var(--field);
  padding-block:clamp(1rem,3vw,2rem);
}

.review-success__title{
  font-size:var(--step-2);
}

/* The panel takes focus when it appears, and the outline that comes with that
   would read as an error on a piece of static copy. */
.review-success__title:focus{
  outline:none;
}

.review-success__body{
  margin-block:.75rem 2rem;
  color:var(--kh-muted);
}


/* ==========================================================================
   FOCUS
   base.css leaves the UA ring in place; the form is where it has to be
   deliberate, so it is stated once here for everything on this page.
   ========================================================================== */

.review-form :focus-visible,
.review-success :focus-visible{
  outline:2px solid var(--kh-copper-deep);
  outline-offset:2px;
}

.field__control:focus-visible{
  outline-offset:0;
  border-color:var(--kh-copper);
}


/* ==========================================================================
   WIDER THAN A PHONE
   ========================================================================== */

@media (min-width:600px){
  .review-form{
    grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:1.25rem;
  }

  /* Only the two name fields share a row. */
  .review-form > .field:not(.field--half),
  .review-form > .review-form__status,
  .review-form > .review-form__submit{
    grid-column:1 / -1;
  }
}


/* ==========================================================================
   TABLET  (768px – 1023px)
   ========================================================================== */

@media (min-width:768px) and (max-width:1023.98px){
  .review-list__grid{
    grid-template-columns:repeat(2,minmax(0,1fr));
  }
}


/* ==========================================================================
   PHONES  (< 768px)
   ========================================================================== */

@media (max-width:767.98px){
  .review-list__grid{
    grid-template-columns:minmax(0,1fr);
  }
}


/* ==========================================================================
   RTL
   The stars and the photo row mirror through flexbox and logical properties,
   so all that is left is the Latin tracking.
   ========================================================================== */

[dir="rtl"] .field__label{
  letter-spacing:0;
}
