4726 Resultados disponibles

Filtrar:

(3056)
(1670)
(0)
Se ha producido un error al procesar la plantilla.
The following has evaluated to null or missing:
==> getProduct(channelId, entry.getTitle())  [in template "34352066712900#33336#65792029" at line 32, column 28]

----
Tip: If the failing expression is known to legally refer to something that's sometimes null or missing, either specify a default value like myOptionalVar!myDefault, or use <#if myOptionalVar??>when-present<#else>when-missing</#if>. (These only cover the last step of the expression; to cover the whole expression, use parenthesis: (myOptionalVar.foo)!myDefault, (myOptionalVar.foo)??
----

----
FTL stack trace ("~" means nesting-related):
	- Failed at: #assign product = getProduct(channelI...  [in template "34352066712900#33336#65792029" at line 32, column 9]
----
1<#setting url_escaping_charset="UTF-8"> 
2 
3<#-- ===== Idiomas: helpers y datos al inicio ===== --> 
4<#function getListTypeEntriesByERC erc> 
5  <#attempt> 
6    <#return restClient.get( 
7      "/headless-admin-list-type/v1.0/list-type-definitions/by-external-reference-code/${erc}/list-type-entries?fields=key,name&sort" 
8    ).items> 
9  <#recover> 
10    <#return []> 
11  </#attempt> 
12</#function> 
13 
14<#-- Siempre lista, nunca null --> 
15<#assign LANG_ENTRIES = (getListTypeEntriesByERC("IDIOMAS_NORMAS_PICKLIST")?default([]))![]> 
16 
17<#function langLiteral key> 
18  <#assign k =   (key!"")?upper_case> 
19  <#list LANG_ENTRIES as e> 
20    <#if (e.key!"")?upper_case == k> 
21      <#return e.name!""> 
22    </#if> 
23  </#list> 
24  <#return key!"" > 
25</#function> 
26 
27<section class="list-standards-section"> 
28  <div class="standards-container view-grid"> 
29    <#if entries?has_content> 
30      <#assign channelId = getChannelId()> 
31      <#list entries as entry> 
32        <#assign product = getProduct(channelId, entry.getTitle())> 
33        <#assign productId = product.productId /> 
34        <#assign cpDefinitionId = product.id /> 
35        <#assign productERC = product.externalReferenceCode /> 
36        <#assign categories = getProductCategories(channelId, product.productId)![]> 
37        <#assign specs = getProductSpecifications(channelId, product.productId)![]> 
38        <#assign status = getStatus(categories)!"" > 
39        <#assign organism = getOrganism(categories)!"" > 
40        <#assign currentStateDate = getCurrentStateDate(specs)!"" > 
41				<#assign entryUrl = ""> 
42        <#attempt> 
43          <#-- si el entry trae slug --> 
44          <#assign entryUrl = "/web/tienda/p/${entry.getUrl()}"> 
45        <#recover> 
46          <#-- si no, usa viewURL o el slug del product --> 
47          <#assign entryUrl = (entry.getViewURL()!"")> 
48          <#if !entryUrl?has_content && (product.slug?? && product.slug?has_content)> 
49            <#assign entryUrl = "/web/tienda/p/${product.slug}"> 
50          </#if> 
51          <#if !entryUrl?has_content> 
52            <#assign entryUrl = "#"> 
53          </#if> 
54        </#attempt> 
55 
56        <#-- Detalle de normas (idioma, formato, precio) --> 
57        <#assign normasDetails = getNormasDetails(product.id)![]> 
58 
59        <#-- idiomas únicos --> 
60        <#assign languages = []> 
61        <#list normasDetails as n> 
62          <#if n.language?? && n.language?has_content && !languages?seq_contains(n.language)> 
63            <#assign languages = languages + [n.language]> 
64          </#if> 
65        </#list> 
66 
67        <#-- combinación por defecto --> 
68        <#assign defaultLang = ""> 
69        <#assign defaultFmt  = ""> 
70        <#assign defaultPrice = 0> 
71        <#if normasDetails?has_content> 
72          <#assign defaultLang = (normasDetails[0].language!"")> 
73          <#assign defaultFmt  = (normasDetails[0].format!"")> 
74          <#assign defaultPrice = (normasDetails[0].price!'0')?number> 
75        </#if> 
76 
77        <#-- formatos válidos para el idioma por defecto --> 
78        <#assign formatsForDefault = []> 
79        <#list normasDetails?filter(nd -> (nd.language!"") == defaultLang) as nd> 
80          <#if nd.format?? && nd.format?has_content && !formatsForDefault?seq_contains(nd.format)> 
81            <#assign formatsForDefault = formatsForDefault + [nd.format]> 
82          </#if> 
83        </#list> 
84        <#if formatsForDefault?has_content && !formatsForDefault?seq_contains(defaultFmt)> 
85          <#assign defaultFmt = formatsForDefault[0]> 
86        </#if> 
87 
88        <#-- precio real para la combinación por defecto --> 
89        <#list normasDetails as nd> 
90          <#if (nd.language!"") == defaultLang && (nd.format!"") == defaultFmt> 
91            <#assign defaultPrice = (nd.price!'0')?number> 
92          </#if> 
93        </#list> 
94					 
95        <#assign hasOptions = (languages?has_content && formatsForDefault?has_content && (defaultLang?has_content) && (defaultFmt?has_content))> 
96 
97        <div class="item-standard" 
98             data-entrytype="Norma" 
99             data-code="${(product.externalReferenceCode!entry.getTitle())?html}" 
100             data-title="${product.name?html}"> 
101          <#if organism?has_content> 
102            <div class="tag-standard">${organism}</div> 
103          <#else> 
104            <div class="tag-standard">TAG</div> 
105          </#if> 
106 
107          <div class="info-standard"> 
108            <a href=${entryUrl} data-senna-off="true"><h3 class="title-standard">${product.name}</h3></a> 
109 
110            <div class="status-box"> 
111 
112                <#if status?? && status?has_content> 
113                    <#assign statusTagClass = ''> 
114 
115              	    <#if status?trim?upper_case == 'EN VIGOR'> 
116              		    <#assign statusTagClass = 'tag-success'> 
117              	    <#elseif status?trim?upper_case == 'ANULADA'> 
118              		    <#assign statusTagClass = 'tag-danger'> 
119                    <#elseif status?trim?upper_case == 'PROYECTO'> 
120              		    <#assign statusTagClass = 'tag-blue'> 
121              	    </#if> 
122 
123              	    <#if statusTagClass?? && statusTagClass?has_content> 
124                        <#assign statusTagClass = "status-standard " + statusTagClass> 
125              	    </#if> 
126 
127              	    <div class="badge ${statusTagClass}">${status}</div> 
128                </#if> 
129 
130              <span class="date-standard"> 
131                <#if currentStateDate?has_content> 
132                  ${currentStateDate?date.iso?string('yyyy-MM-dd')} 
133                <#else> 
134
135                </#if> 
136              </span> 
137            </div> 
138 
139            <div class="description-text"> 
140              ${product.description} 
141            </div> 
142								 
143								<#if author?has_content>${author?html}<#else>&nbsp;</#if> 
144 
145            <div class="price-container"> 
146              <span class="price price-ae"></span> 
147            </div> 
148 
149            <div data-productid="${productId}" data-erc="${productERC}" class="options-standard selector-language_format"> 
150                <#if hasOptions> 
151                  <select class="form-control select-language"> 
152                    <#list languages as l> 
153                      <option value="${l?html}" <#if l == defaultLang>selected</#if>> 
154                        ${langLiteral(l)?html} 
155                      </option> 
156                    </#list> 
157                  </select> 
158                  <select class="form-control select-format"> 
159                    <#list formatsForDefault as f> 
160                      <option value="${f?html}" <#if f == defaultFmt>selected</#if>> 
161                        ${f?html} 
162                      </option> 
163                    </#list> 
164                  </select> 
165                <#else> 
166                  <select class="form-control select-language" disabled><option>–</option></select> 
167                  <select class="form-control select-format" disabled><option>–</option></select> 
168                </#if> 
169            </div> 
170 
171            <a href="#" 
172               class="standard-button <#if !hasOptions>disabled</#if>" 
173               aria-disabled="<#if !hasOptions>true<#else>false</#if>"> 
174              <#if hasOptions>Añadir a la cesta<#else>No disponible</#if> 
175            </a> 
176          </div> 
177 
178          <#-- Datos para JS --> 
179          <#if hasOptions> 
180            <script type="application/json" class="normas-data">[ 
181              <#list normasDetails as n> 
182                <#-- solo pares válidos --> 
183                <#if (n.language?? && n.language?has_content) && (n.format?? && n.format?has_content)> 
184
185                  "format": "${(n.format!"")?js_string}", 
186                  "language": "${(n.language!"")?js_string}", 
187                  "price": ${(n.price!'0')?c} 
188                }<#if n_has_next>,</#if> 
189                </#if> 
190              </#list> 
191            ]</script> 
192            <script type="application/json" class="lang-map">{ 
193              <#list languages as l> 
194                "${(l!"")?upper_case?js_string}": "${langLiteral(l)?js_string}"<#if l_has_next>,</#if> 
195              </#list> 
196            }</script> 
197          </#if> 
198        </div> 
199      </#list> 
200    <#else> 
201        <div class="search-results-add-custom-empty-message"></div> 
202    </#if> 
203  </div> 
204</section> 
205 
206<#-- ===== Helpers REST ===== --> 
207<#function getChannelId> 
208  <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels?filter=name eq 'Aenor España'&sort").items[0].id> 
209</#function> 
210 
211<#function getProduct channelId name> 
212  <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${channelId}/products?filter=name eq '${name?url}'&sort").items[0]> 
213</#function> 
214 
215<#function getProductCategories channelId productId> 
216  <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${channelId}/products/${productId}/categories?sort").items> 
217</#function> 
218 
219<#function getProductSpecifications channelId productId> 
220  <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${channelId}/products/${productId}/product-specifications?sort").items> 
221</#function> 
222 
223<#function getCurrentStateDate specifications> 
224  <#list specifications as specification> 
225    <#if specification.specificationKey == 'current-state-date'> 
226      <#return specification.value> 
227    </#if> 
228  </#list> 
229</#function> 
230 
231<#function getStatus categories> 
232  <#list categories as category> 
233    <#if category.vocabulary == 'status'> 
234      <#return category.title> 
235    </#if> 
236  </#list> 
237</#function> 
238 
239<#function getOrganism categories> 
240  <#list categories as category> 
241    <#if category.vocabulary == 'organismos'> 
242      <#return category.name> 
243    </#if> 
244  </#list> 
245</#function> 
246 
247<#function getNormasDetails productId> 
248  <#return restClient.get("/c/standards/?filter=r_standards_CPDefinitionId eq '${productId}'").items> 
249</#function> 
250 
251<script> 
252jQuery(async function($){ 
253  let API_HOST = null; 
254  function euros(v){ 
255    var n = Number(v) || 0; 
256    return n.toLocaleString('es-ES', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' €'; 
257
258  function uniq(a){ return Array.from(new Set(a)); } 
259 
260  async function waitForEcomGlobalScripts(timeoutMs){ 
261    const start = Date.now(); 
262    return new Promise((resolve, reject) => { 
263      (function check(){ 
264        if (window.ecomGlobalScripts?.functions?.getFieldCXCustomConfig && window.ecomGlobalScripts?.properties?.cxCustomConfigsNames) { 
265          return resolve(); 
266
267        if (Date.now() - start > timeoutMs) return reject(new Error('ecomGlobalScripts no disponible a tiempo')); 
268        requestAnimationFrame(check); 
269      })(); 
270    }); 
271
272 
273  const getApiHost = async () => { 
274    if (API_HOST) return API_HOST; 
275    try { 
276      await waitForEcomGlobalScripts(5000); 
277      API_HOST = await window.ecomGlobalScripts.functions.getFieldCXCustomConfig( 
278        window.ecomGlobalScripts.properties.cxCustomConfigsNames.defaultName, "webApiUrl" 
279      ); 
280    } catch (err) { 
281      console.error('No se pudo resolver API_HOST', err); 
282
283    return API_HOST; 
284  }; 
285 
286  function fill($sel, values, textFn){ 
287    var keep = $sel.val(); 
288    $sel.empty(); 
289    values.forEach(function(v){ 
290      $sel.append($('<option>', { value: v, text: textFn ? textFn(v) : v })); 
291    }); 
292    if(keep && values.indexOf(keep) !== -1){ $sel.val(keep); } 
293    else if(values.length){ $sel.val(values[0]); } 
294
295 
296  function relabel($sel, textFn){ 
297    $sel.find('option').each(function(){ 
298      var v = $(this).attr('value'); 
299      $(this).text(textFn ? textFn(v) : v); 
300    }); 
301
302 
303  function toUC(s){ return (s||'').toString().toUpperCase(); } 
304  function emitCartError(msg){ 
305    try { 
306      window.dispatchEvent(new CustomEvent('cart:error', { detail: { message: msg || 'Error al añadir el producto a la cesta' } })); 
307    } catch (e) {} 
308
309  async function resolveProductId(entryType, code, codIdioma, codFormato){ 
310    const host = await getApiHost(); 
311    if (!host) return ''; 
312    try{ 
313      var res = await fetch(host + '/product/getProductId', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({ entryType: entryType, code: code, codIdioma: codIdioma, codFormato: codFormato }), credentials:'omit' }); 
314      if(!res.ok) throw new Error('HTTP '+res.status); 
315      var data = await res.json(); 
316      return (data && (data.id)) || ''; 
317    } catch(e){ return ''; } 
318
319  function getQueue(){ try { return JSON.parse(localStorage.getItem('cartQueued') || '[]'); } catch(e){ return []; } } 
320  function setQueue(q){ localStorage.setItem('cartQueued', JSON.stringify(q)); } 
321  function queueItem(item){ 
322    var q=getQueue(); 
323    var pid=(item&&item.productid)?String(item.productid):''; 
324    var amt=Number(item&&item.amount)||1; 
325    var prc=(item&&typeof item.price!=='undefined')?Number(item.price):undefined; 
326    var nm =(item&&typeof item.name!=='undefined')?String(item.name):undefined; 
327    var ci =(item&&typeof item.idioma!=='undefined')?String(item.idioma):undefined; 
328    var cf =(item&&typeof item.formato!=='undefined')?String(item.formato):undefined; 
329    if(!pid) return; 
330    var idx=-1; for(var i=0;i<q.length;i++){ var qp=q[i]&&q[i].productid?String(q[i].productid):''; if(qp===pid){ idx=i; break; } } 
331    if(idx>=0){ var cur=Number(q[idx].amount)||0; q[idx].amount=Math.max(1, cur+amt); if(typeof prc!=='undefined'){ q[idx].price=prc; } if(typeof nm!=='undefined'){ q[idx].name=nm;} if(typeof ci!=='undefined'){ q[idx].idioma=ci;} if(typeof cf!=='undefined'){ q[idx].formato=cf;} } 
332    else { var obj={ amount: Math.max(1,amt), productid: pid }; if(typeof prc!=='undefined') obj.price=prc; if(typeof nm!=='undefined') obj.name=nm; if(typeof ci!=='undefined') obj.idioma=ci; if(typeof cf!=='undefined') obj.formato=cf; q.push(obj); } 
333    setQueue(q); 
334
335  function bumpBadge(amt){ var cur=parseInt(localStorage.getItem('cartCount')||'0',10)||0; var next=Math.max(0, cur+(amt|0)); localStorage.setItem('cartCount', String(next)); window.dispatchEvent(new CustomEvent('cart:updated', { detail:{ count: next }})); } 
336 
337  function initStandardCard($card){ 
338    var dataNode = $card.find('script.normas-data')[0]; 
339    if(!dataNode) return; // sin datos -> nada que sincronizar 
340 
341    var data = []; 
342    try { data = JSON.parse(dataNode.textContent); } catch(e) { data = []; } 
343    if(!data.length) return; 
344 
345    var mapNode = $card.find('script.lang-map')[0]; 
346    var langMap = {}; 
347    try { if(mapNode) langMap = JSON.parse(mapNode.textContent); } catch(e) { langMap = {}; } 
348 
349    var $lang  = $card.find('.select-language'); 
350    var $fmt   = $card.find('.select-format'); 
351    var $price = $card.find('.price-ae'); 
352 
353    function labelOf(lang){ return langMap[toUC(lang)] || lang; } 
354    function formatsFor(lang){ 
355      return uniq(data.filter(function(d){ return d.language === lang; }).map(function(d){ return d.format; })); 
356
357    function languagesFor(fmt){ 
358      return uniq(data.filter(function(d){ return d.format === fmt; }).map(function(d){ return d.language; })); 
359
360    function priceOf(lang, fmt){ 
361      var m = data.find(function(d){ return d.language === lang && d.format === fmt; }); 
362      return m ? Number(m.price) || 0 : 0; 
363
364 
365    function onLanguageChange(){ 
366      var lang = $lang.val(); 
367      var fmts = formatsFor(lang); 
368      fill($fmt, fmts, null); 
369      $price.text(euros(priceOf(lang, $fmt.val()))); 
370
371    function onFormatChange(){ 
372      var fmt   = $fmt.val(); 
373      var langs = languagesFor(fmt); 
374      fill($lang, langs, labelOf); 
375      $price.text(euros(priceOf($lang.val(), fmt))); 
376
377 
378    var l0 = $lang.val(); 
379    var f0 = $fmt.val(); 
380    if(!data.find(function(d){ return d.language === l0 && d.format === f0; })){ 
381      onLanguageChange(); 
382    } else { 
383      $price.text(euros(priceOf(l0, f0))); 
384
385 
386    relabel($lang, labelOf); // literal de idioma 
387 
388    $lang.off('change.std').on('change.std', onLanguageChange); 
389    $fmt.off('change.std').on('change.std', onFormatChange); 
390 
391    // Añadir a la cesta 
392    $card.find('.standard-button').off('click.add').on('click.add', async function(e){ 
393      e.preventDefault(); 
394      var orderId = localStorage.getItem('salesOrderId'); 
395      var entryType = ($card.data('entrytype') || 'Norma'); 
396      var code = ($card.data('code') || '').toString(); 
397      var codIdioma = ($lang.val() || '').toString(); 
398      var codFormato = ($fmt.val() || '').toString(); 
399      if (!code) { code = ($card.find('.title-standard').text() || '').trim(); } 
400      var priceToSend = Number(priceOf($lang.val(), $fmt.val())) || 0; 
401      var resolvedId = await resolveProductId(entryType, code, codIdioma, codFormato); 
402      if (!resolvedId) { 
403        emitCartError('Error al añadir el producto a la cesta'); 
404        return; 
405
406      var productIdForCart = resolvedId; 
407      if (orderId) { 
408        var host = await getApiHost(); 
409        if (!host) { 
410          emitCartError('Error al añadir el producto a la cesta'); 
411          return; 
412
413        var payload = { 
414          salesorderid: orderId || '', 
415          amount: 1, 
416          productid: productIdForCart, 
417          price: priceToSend, 
418          name: ($card.data('title') || '').toString(), 
419          idioma: codIdioma, 
420          formato: codFormato 
421        }; 
422        bumpBadge(1); 
423        fetch(host + '/shoppingProcess/newSalesOrderProduct', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(payload), credentials:'omit' }) 
424          .then(function(r){ if(!r.ok) throw new Error('HTTP '+r.status); setTimeout(function(){ window.dispatchEvent(new CustomEvent('cart:updated')); }, 300); }) 
425          .catch(function(){ bumpBadge(-1); emitCartError('Error al añadir el producto a la cesta'); }); 
426      } else { 
427        queueItem({ amount: 1, productid: productIdForCart, price: priceToSend, name: ($card.data('title')||'').toString(), idioma: codIdioma, formato: codFormato }); 
428        bumpBadge(1); 
429
430    }); 
431
432 
433  // Alturas por fila 
434  function adjustHeightsByRow(){ 
435    var $cards = $('.list-standards-section .item-standard'); 
436    var $titles = $cards.find('.title-standard'); 
437    var $descs  = $cards.find('.description-text'); 
438    var $infos  = $cards.find('.info-standard'); 
439 
440    $cards.css('height','auto'); 
441    $titles.css('height','auto'); 
442    $descs.css('height','auto'); 
443    $infos.css('height','auto'); 
444 
445    if($(window).width() <= 767.98) return; 
446 
447    var rows = []; 
448    var tol = 4; // tolerancia de alineación 
449    $cards.each(function(){ 
450      var $c = $(this); 
451      var top = Math.round($c.position().top); 
452      var row = rows.find(function(r){ return Math.abs(r.top - top) <= tol; }); 
453      if(!row){ row = { top: top, cards: [] }; rows.push(row); } 
454      row.cards.push($c); 
455    }); 
456 
457    rows.forEach(function(r){ 
458      var hCard = 0, hTitle = 0, hDesc = 0, hInfo = 0; 
459      r.cards.forEach(function($c){ 
460        hCard  = Math.max(hCard, $c.outerHeight()); 
461        hTitle = Math.max(hTitle, $c.find('.title-standard').outerHeight()); 
462        hDesc  = Math.max(hDesc, $c.find('.description-text').outerHeight()); 
463        hInfo  = Math.max(hInfo, $c.find('.info-standard').outerHeight()); 
464      }); 
465      r.cards.forEach(function($c){ 
466        $c.height(hCard); 
467        $c.find('.title-standard').height(hTitle); 
468        $c.find('.description-text').height(hDesc); 
469        $c.find('.info-standard').height(hInfo); 
470      }); 
471    }); 
472
473 
474  async function init(){ 
475    $('.list-standards-section .item-standard').each(function(){ initStandardCard($(this)); }); 
476    adjustHeightsByRow(); 
477    setTimeout(adjustHeightsByRow, 50); 
478
479 
480  var so = localStorage.getItem('salesOrderId'); // flushQueue gestionado por header 
481  await init(); 
482  $(window).on('resize', init); 
483}); 
484</script> 
485 
486<style> 
487.list-standards-section { margin: 40px auto 35px; } 
488.list-standards-section .header-section { border-bottom: 1px solid #dbdbdb; margin-bottom: 32px; display: flex; justify-content: space-between; margin-left: 2px; margin-right: 2px; align-items: center; } 
489.list-standards-section .header-section .order-elements { font-family: Segoe-UI-This; font-size: 16px; font-weight: 400; line-height: 23px; text-align: left; color: #2d2d2b; } 
490.list-standards-section .title-section { font-family: SohoStd-Medium; font-size: 24px; font-weight: 500; line-height: 28.8px; text-align: left; color: var(--brand-color-3, #29337f); } 
491.list-standards-section .standards-container { display: flex; flex-wrap: wrap; gap: 20px 0; padding-right: 0; padding-left: 0; } 
492.list-standards-section .item-standard { position: relative; border: 1px solid #e0e0e0; padding: 16px 14px; border-radius: 4px; display: flex; flex-direction: column; } 
493.list-standards-section .tag-standard { position: absolute; top: -10px; left: 16px; padding: 4px 10px; border-radius: 4px; background-color: #6a9bd3; color: #fff; font-weight: bold; font-size: 12px; z-index: 5; } 
494.list-standards-section .date-ISO { font-family: Segoe-UI-This; font-size: 14px; font-weight: 400; line-height: 18.62px; text-align: left; color: #444; } 
495.list-standards-section .title-standard { font-family: SohoGothicPro-Regular; font-size: 16px; font-weight: bold; color: #1a4b94; line-height: 24px; text-align: left; padding-top: 10px;} 
496.list-standards-section .description-text { margin-top: 10px; margin-bottom: 12px; font-family: SohoGothicPro-Regular; font-weight: 400; line-height: 24px; font-size: 13px; text-align: left; color: #333; } 
497.list-standards-section .info-standard { display: flex; flex-direction: column; flex: 1; } 
498.list-standards-section .info-standard .status-box .tag-success {background: #2a7a36; color: #fff;} 
499.list-standards-section .info-standard .status-box .tag-danger {background: #c00000; color: #fff;} 
500.list-standards-section .info-standard .status-box .tag-blue {background: #0078c0; color: #fff;} 
501.list-standards-section .price-container { display: flex; flex-direction: column; text-align: left; letter-spacing: -0.02em; margin-top: auto; margin-bottom: 16px; } 
502.list-standards-section .price-container .price-ae { font-size: 23px; font-weight: bold; line-height: 22px; margin-bottom: 10px; color: var(--brand-color-1, #1f57a3); } 
503.list-standards-section .standard-button { padding: 17px; width: 100%; text-align: center; display: block; background-color: var(--brand-color-1, #1f57a3); color: #fff; text-transform: uppercase; font-family: SohoStd-Medium; font-size: 14px; font-weight: 500; line-height: 14px; text-decoration: none; } 
504.list-standards-section .standard-button.disabled { opacity: .6; pointer-events: none; } 
505.list-standards-section .view-grid{ gap: 20px 3.5%; } 
506.list-standards-section .view-grid .item-standard { width: 31%; } 
507@media (max-width:1200px){ .list-standards-section .view-grid .item-standard { width: 48%; } } 
508@media (max-width: 576px) { .list-standards-section .view-grid .item-standard { width: 100%; } } 
509.options-standard { display: flex; gap: 10px; margin-bottom: 16px; border: none; } 
510.options-standard .select-language, 
511.options-standard .select-format { 
512  background-color: #f5f5f5; 
513  border: 1px solid #d0d0d0; 
514  color: #2d2d2b; 
515  font-size: 13px; 
516  height: 38px; 
517
518.options-standard .select-language:disabled, 
519.options-standard .select-format:disabled { 
520  background-color: #f5f5f5; 
521  color: #2d2d2b; 
522  opacity: 1; 
523
524.options-standard .select-language { flex: 2; } 
525.options-standard .select-format { flex: 1; } 
526select.form-control, 
527select.form-control:focus, 
528select.form-control:focus-visible { 
529  background-image: url(/documents/d/global/ico-chevron-down); 
530  background-size: 18px 10px; 
531  background-position-x: 95%; 
532  background-repeat: no-repeat; 
533  position: relative; 
534
535.status-standard { margin-right: 10px; background-color: #107510; color: white; font-size: 12px; padding: 2px 6px; border-radius: 3px; font-weight: bold; } 
536.date-standard { font-size: 12px; color: #666; } 
537.js-checks-container { display: none; } 
538</style>