AENOR Logo

Normas IEEE

4907 Resultados disponibles

Filtrar:

(3104)
(1803)
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#153601689" 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#153601689" 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 = "/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 = "/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-result-buscador 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            <#if hasOptions> 
150              <div data-productid="${productId}" data-erc="${productERC}" class="options-standard selector-language_format"> 
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              </div> 
166            <#else>                 
167              <div class="standard-not-available"> 
168                Si desea adquirir esta norma, envíenos su solicitud a <a href="mailto:normas@aenor.com">normas@aenor.com</a> 
169              </div> 
170            </#if> 
171 
172            <#if hasOptions> 
173            <button 
174               class="standard-button" 
175               aria-disabled="false"> 
176              ${languageUtil.get(locale, "ecom-add_cart")} 
177            </button> 
178            </#if> 
179          </div> 
180 
181          <#-- Datos para JS --> 
182          <#if hasOptions> 
183            <script type="application/json" class="normas-data">[ 
184              <#list normasDetails as n> 
185                <#-- solo pares válidos --> 
186                <#if (n.language?? && n.language?has_content) && (n.format?? && n.format?has_content)> 
187
188                  "format": "${(n.format!"")?js_string}", 
189                  "language": "${(n.language!"")?js_string}", 
190                  "price": ${(n.price!'0')?c} 
191                }<#if n_has_next>,</#if> 
192                </#if> 
193              </#list> 
194            ]</script> 
195            <script type="application/json" class="lang-map">{ 
196              <#list languages as l> 
197                "${(l!"")?upper_case?js_string}": "${langLiteral(l)?js_string}"<#if l_has_next>,</#if> 
198              </#list> 
199            }</script> 
200          </#if> 
201        </div> 
202      </#list> 
203    <#else> 
204        <div class="search-results-add-custom-empty-message"></div> 
205    </#if> 
206  </div> 
207</section> 
208 
209<#-- ===== Helpers REST ===== --> 
210<#function getChannelId> 
211  <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels?filter=name eq 'Aenor España'&sort").items[0].id> 
212</#function> 
213 
214<#function getProduct channelId name> 
215  <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${channelId}/products?filter=name eq '${name?url}'&sort").items[0]> 
216</#function> 
217 
218<#function getProductCategories channelId productId> 
219  <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${channelId}/products/${productId}/categories?sort").items> 
220</#function> 
221 
222<#function getProductSpecifications channelId productId> 
223  <#return restClient.get("/headless-commerce-delivery-catalog/v1.0/channels/${channelId}/products/${productId}/product-specifications?sort").items> 
224</#function> 
225 
226<#function getCurrentStateDate specifications> 
227  <#list specifications as specification> 
228    <#if specification.specificationKey == 'current-state-date'> 
229      <#return specification.value> 
230    </#if> 
231  </#list> 
232</#function> 
233 
234<#function getStatus categories> 
235  <#list categories as category> 
236    <#if category.vocabulary == 'status'> 
237      <#return category.title> 
238    </#if> 
239  </#list> 
240</#function> 
241 
242<#function getOrganism categories> 
243  <#list categories as category> 
244    <#if category.vocabulary == 'organismos'> 
245      <#return category.name> 
246    </#if> 
247  </#list> 
248</#function> 
249 
250<#function getNormasDetails productId> 
251  <#return restClient.get("/c/standards/?filter=r_standards_CPDefinitionId eq '${productId}'").items> 
252</#function> 
253 
254<script> 
255jQuery(async function($){ 
256  let API_HOST = null; 
257  function euros(v){ 
258    var n = Number(v) || 0; 
259    return n.toLocaleString('es-ES', { minimumFractionDigits: 2, maximumFractionDigits: 2 }) + ' €'; 
260
261  function uniq(a){ return Array.from(new Set(a)); } 
262 
263  async function waitForEcomGlobalScripts(timeoutMs){ 
264    const start = Date.now(); 
265    return new Promise((resolve, reject) => { 
266      (function check(){ 
267        if (window.ecomGlobalScripts?.functions?.getFieldCXCustomConfig && window.ecomGlobalScripts?.properties?.cxCustomConfigsNames) { 
268          return resolve(); 
269
270        if (Date.now() - start > timeoutMs) return reject(new Error('ecomGlobalScripts no disponible a tiempo')); 
271        requestAnimationFrame(check); 
272      })(); 
273    }); 
274
275 
276  const getApiHost = async () => { 
277    if (API_HOST) return API_HOST; 
278    try { 
279      await waitForEcomGlobalScripts(5000); 
280      API_HOST = await window.ecomGlobalScripts.functions.getFieldCXCustomConfig( 
281        window.ecomGlobalScripts.properties.cxCustomConfigsNames.defaultName, "webApiUrl" 
282      ); 
283    } catch (err) { 
284      console.error('No se pudo resolver API_HOST', err); 
285
286    return API_HOST; 
287  }; 
288 
289  function fill($sel, values, textFn){ 
290    var keep = $sel.val(); 
291    $sel.empty(); 
292    values.forEach(function(v){ 
293      $sel.append($('<option>', { value: v, text: textFn ? textFn(v) : v })); 
294    }); 
295    if(keep && values.indexOf(keep) !== -1){ $sel.val(keep); } 
296    else if(values.length){ $sel.val(values[0]); } 
297
298 
299  function relabel($sel, textFn){ 
300    $sel.find('option').each(function(){ 
301      var v = $(this).attr('value'); 
302      $(this).text(textFn ? textFn(v) : v); 
303    }); 
304
305 
306  function toUC(s){ return (s||'').toString().toUpperCase(); } 
307  function emitCartError(msg){ 
308    try { 
309      window.dispatchEvent(new CustomEvent('cart:error', { detail: { message: msg || 'Error al añadir el producto a la cesta' } })); 
310    } catch (e) {} 
311
312  async function resolveProductId(entryType, code, codIdioma, codFormato){ 
313    const host = await getApiHost(); 
314    if (!host) return ''; 
315    try{ 
316      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' }); 
317      if(!res.ok) throw new Error('HTTP '+res.status); 
318      var data = await res.json(); 
319      return (data && (data.id)) || ''; 
320    } catch(e){ return ''; } 
321
322  function getQueue(){ try { return JSON.parse(localStorage.getItem('cartQueued') || '[]'); } catch(e){ return []; } } 
323  function setQueue(q){ localStorage.setItem('cartQueued', JSON.stringify(q)); } 
324  function queueItem(item){ 
325    var q=getQueue(); 
326    var pid=(item&&item.productid)?String(item.productid):''; 
327    var amt=Number(item&&item.amount)||1; 
328    var prc=(item&&typeof item.price!=='undefined')?Number(item.price):undefined; 
329    var nm =(item&&typeof item.name!=='undefined')?String(item.name):undefined; 
330    var ci =(item&&typeof item.idioma!=='undefined')?String(item.idioma):undefined; 
331    var cf =(item&&typeof item.formato!=='undefined')?String(item.formato):undefined; 
332    if(!pid) return; 
333    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; } } 
334    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;} } 
335    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); } 
336    setQueue(q); 
337
338  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 }})); } 
339 
340  function initStandardCard($card){ 
341    var dataNode = $card.find('script.normas-data')[0]; 
342    if(!dataNode) return; // sin datos -> nada que sincronizar 
343 
344    var data = []; 
345    try { data = JSON.parse(dataNode.textContent); } catch(e) { data = []; } 
346    if(!data.length) return; 
347 
348    var mapNode = $card.find('script.lang-map')[0]; 
349    var langMap = {}; 
350    try { if(mapNode) langMap = JSON.parse(mapNode.textContent); } catch(e) { langMap = {}; } 
351 
352    var $lang  = $card.find('.select-language'); 
353    var $fmt   = $card.find('.select-format'); 
354    var $price = $card.find('.price-ae'); 
355 
356    function labelOf(lang){ return langMap[toUC(lang)] || lang; } 
357    function formatsFor(lang){ 
358      return uniq(data.filter(function(d){ return d.language === lang; }).map(function(d){ return d.format; })); 
359
360    function languagesFor(fmt){ 
361      return uniq(data.filter(function(d){ return d.format === fmt; }).map(function(d){ return d.language; })); 
362
363    function priceOf(lang, fmt){ 
364      var m = data.find(function(d){ return d.language === lang && d.format === fmt; }); 
365      return m ? Number(m.price) || 0 : 0; 
366
367 
368    function onLanguageChange(){ 
369      var lang = $lang.val(); 
370      var fmts = formatsFor(lang); 
371      fill($fmt, fmts, null); 
372      $price.text(euros(priceOf(lang, $fmt.val()))); 
373
374    function onFormatChange(){ 
375      var fmt   = $fmt.val(); 
376      var langs = languagesFor(fmt); 
377      fill($lang, langs, labelOf); 
378      $price.text(euros(priceOf($lang.val(), fmt))); 
379
380 
381    var l0 = $lang.val(); 
382    var f0 = $fmt.val(); 
383    if(!data.find(function(d){ return d.language === l0 && d.format === f0; })){ 
384      onLanguageChange(); 
385    } else { 
386      $price.text(euros(priceOf(l0, f0))); 
387
388 
389    relabel($lang, labelOf); // literal de idioma 
390 
391    $lang.off('change.std').on('change.std', onLanguageChange); 
392    $fmt.off('change.std').on('change.std', onFormatChange); 
393 
394    // Añadir a la cesta 
395    $card.find('.standard-button').off('click.add').on('click.add', function(e){ 
396      var btn = this; 
397      if ($(btn).hasClass('disabled')) { e.preventDefault(); return; } 
398      var run = async function(){ 
399        e.preventDefault(); 
400      var orderId = localStorage.getItem('salesOrderId'); 
401      var entryType = ($card.data('entrytype') || 'Norma'); 
402      var code = ($card.data('code') || '').toString(); 
403      var $langSel = $card.find('.select-language'); 
404      var $fmtSel = $card.find('.select-format'); 
405      var codIdioma = ($langSel.filter(function(){ return this.value; }).first().val() || $langSel.val() || '').toString(); 
406      var codFormato = ($fmtSel.filter(function(){ return this.value; }).first().val() || $fmtSel.val() || '').toString(); 
407      if ((!codIdioma || !codFormato) && data && data.length){ 
408        codIdioma = codIdioma || (data[0].language || data[0].codLanguage || ''); 
409        codFormato = codFormato || (data[0].format || data[0].codFormat || ''); 
410
411      if (!code) { code = ($card.find('.title-standard').text() || '').trim(); } 
412      var priceToSend = Number(priceOf(codIdioma, codFormato)) || 0; 
413      var resolvedId = await resolveProductId(entryType, code, codIdioma, codFormato); 
414      if (!resolvedId) { 
415        emitCartError('Error al añadir el producto a la cesta'); 
416        return; 
417
418      var productIdForCart = resolvedId; 
419      if (orderId) { 
420        var host = await getApiHost(); 
421        if (!host) { 
422          emitCartError('Error al añadir el producto a la cesta'); 
423          return; 
424
425        var payload = { 
426          salesorderid: orderId || '', 
427          amount: 1, 
428          productid: productIdForCart, 
429          price: priceToSend, 
430          name: ($card.data('title') || '').toString(), 
431          idioma: codIdioma, 
432          formato: codFormato 
433        }; 
434        bumpBadge(1); 
435        fetch(host + '/shoppingProcess/newSalesOrderProduct', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(payload), credentials:'omit' }) 
436          .then(function(r){ if(!r.ok) throw new Error('HTTP '+r.status); setTimeout(function(){ window.dispatchEvent(new CustomEvent('cart:updated')); }, 300); }) 
437          .catch(function(){ bumpBadge(-1); emitCartError('Error al añadir el producto a la cesta'); }); 
438      } else { 
439        queueItem({ amount: 1, productid: productIdForCart, price: priceToSend, name: ($card.data('title')||'').toString(), idioma: codIdioma, formato: codFormato }); 
440        bumpBadge(1); 
441
442      }; 
443      var helper = window.ecomGlobalScripts?.functions?.withButtonSpinner; 
444      if (typeof helper === 'function') { 
445        return helper(btn, run, { spinnerClass: 'spinner-border spinner-border-sm text-light', mode: 'replace' }); 
446
447      return run(); 
448    }); 
449
450 
451  // Alturas por fila 
452  function adjustHeightsByRow(){ 
453    var $cards = $('.list-standards-section .item-standard'); 
454    var $titles = $cards.find('.title-standard'); 
455    var $descs  = $cards.find('.description-text'); 
456    var $infos  = $cards.find('.info-standard'); 
457 
458    $cards.css('height','auto'); 
459    $titles.css('height','auto'); 
460    $descs.css('height','auto'); 
461    $infos.css('height','auto'); 
462 
463    if($(window).width() <= 767.98) return; 
464 
465    var rows = []; 
466    var tol = 4; // tolerancia de alineación 
467    $cards.each(function(){ 
468      var $c = $(this); 
469      var top = Math.round($c.position().top); 
470      var row = rows.find(function(r){ return Math.abs(r.top - top) <= tol; }); 
471      if(!row){ row = { top: top, cards: [] }; rows.push(row); } 
472      row.cards.push($c); 
473    }); 
474 
475    rows.forEach(function(r){ 
476      var hCard = 0, hTitle = 0, hDesc = 0, hInfo = 0; 
477      r.cards.forEach(function($c){ 
478        hCard  = Math.max(hCard, $c.outerHeight()); 
479        hTitle = Math.max(hTitle, $c.find('.title-standard').outerHeight()); 
480        hDesc  = Math.max(hDesc, $c.find('.description-text').outerHeight()); 
481        hInfo  = Math.max(hInfo, $c.find('.info-standard').outerHeight()); 
482      }); 
483      r.cards.forEach(function($c){ 
484        $c.height(hCard); 
485        $c.find('.title-standard').height(hTitle); 
486        $c.find('.description-text').height(hDesc); 
487        $c.find('.info-standard').height(hInfo); 
488      }); 
489    }); 
490
491 
492  async function init(){ 
493    $('.list-standards-section .item-standard').each(function(){ initStandardCard($(this)); }); 
494    adjustHeightsByRow(); 
495    setTimeout(adjustHeightsByRow, 50); 
496
497 
498  var so = localStorage.getItem('salesOrderId'); // flushQueue gestionado por header 
499  await init(); 
500  $(window).on('resize', init); 
501}); 
502</script> 
503 
504<style> 
505.list-standards-section { margin: 40px auto 35px; } 
506.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; } 
507.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; } 
508.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); } 
509.list-standards-section .standards-container { display: flex; flex-wrap: wrap; gap: 20px 0; padding-right: 0; padding-left: 0; } 
510.list-standards-section .item-standard { position: relative; border: 1px solid #e0e0e0; padding: 16px 14px; border-radius: 4px; display: flex; flex-direction: column; } 
511.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; } 
512.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; } 
513.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;} 
514.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; } 
515.list-standards-section .info-standard { display: flex; flex-direction: column; flex: 1; } 
516.list-standards-section .info-standard .status-box .tag-success {background: #2a7a36; color: #fff;} 
517.list-standards-section .info-standard .status-box .tag-danger {background: #c00000; color: #fff;} 
518.list-standards-section .info-standard .status-box .tag-blue {background: #0078c0; color: #fff;} 
519.list-standards-section .price-container { display: flex; flex-direction: column; text-align: left; letter-spacing: -0.02em; margin-top: auto; margin-bottom: 16px; } 
520.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); } 
521.list-standards-section .standard-not-available { 
522  border-style: solid; 
523  border-width: 2px; 
524  background-color: #f2dede; 
525  border-color: #ebcccc; 
526  color: #a94442; 
527  margin-left: -2px !important; 
528  padding-left: 4px !important; 
529  margin-top: 25px; 
530
531.list-standards-section .standard-button { border: 0; outline: 0; box-shadow: none; appearance: none; -webkit-appearance: none; -moz-appearance: none; 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; cursor: pointer; text-decoration: none; } 
532.list-standards-section .standard-button.disabled, 
533.list-standards-section .standard-button.ecom-btn-loading { 
534  opacity: .6; 
535  pointer-events: none; 
536  filter: brightness(0.85); 
537
538.list-standards-section .standard-button:hover, 
539.list-standards-section .standard-button:focus, 
540.list-standards-section .standard-button:focus-visible, 
541.list-standards-section .standard-button:active { 
542  background-color: var(--brand-color-1, #1f57a3); 
543  color: #fff; 
544  text-decoration: none; 
545  outline: 2px solid var(--brand-color-2, #6a9bd3); 
546  outline-offset: 2px; 
547  box-shadow: 0 0 0 3px rgba(106, 155, 211, 0.35); 
548
549.list-standards-section .standard-button:active { 
550  filter: brightness(0.85); 
551
552.list-standards-section .view-grid{ gap: 20px 3.5%; } 
553.list-standards-section .view-grid .item-standard { width: 31%; } 
554@media (max-width:1200px){ .list-standards-section .view-grid .item-standard { width: 48%; } } 
555@media (max-width: 576px) { .list-standards-section .view-grid .item-standard { width: 100%; } } 
556.options-standard { display: flex; gap: 10px; margin-bottom: 16px; border: none; } 
557.options-standard .select-language, 
558.options-standard .select-format { 
559  background-color: #f5f5f5; 
560  border: 1px solid #d0d0d0; 
561  color: #2d2d2b; 
562  font-size: 13px; 
563  height: 38px; 
564
565.options-standard .select-language:disabled, 
566.options-standard .select-format:disabled { 
567  background-color: #f5f5f5; 
568  color: #2d2d2b; 
569  opacity: 1; 
570
571.options-standard .select-language { flex: 2; } 
572.options-standard .select-format { flex: 1; } 
573select.form-control, 
574select.form-control:focus, 
575select.form-control:focus-visible { 
576  background-image: url(/documents/d/global/ico-chevron-down); 
577  background-size: 18px 10px; 
578  background-position-x: 95%; 
579  background-repeat: no-repeat; 
580  position: relative; 
581
582.status-standard { margin-right: 10px; background-color: #107510; color: white; font-size: 12px; padding: 2px 6px; border-radius: 3px; font-weight: bold; } 
583.date-standard { font-size: 12px; color: #666; } 
584.js-checks-container { display: none; } 
585</style>